gdkintl.h \
gdkkeys.c \
gdkkeyuni.c \
+ gdkoffscreenwindow.c \
gdkpango.c \
gdkpixbuf-drawable.c \
gdkpixbuf-render.c \
gdk_keyboard_grab
gdk_keyboard_grab_info_libgtk_only
gdk_pointer_grab
-gdk_pointer_grab_info_libgtk_only
#endif
#endif
gdk_pointer_ungrab
gdk_event_send_client_message
gdk_event_send_clientmessage_toall
+gdk_pointer_grab_info_libgtk_only
+gdk_display_pointer_is_grabbed
#endif
#endif
#endif
#endif
-#if IN_HEADER(__GDK_PIXMAP_H__)
-#if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_bitmap_create_from_data
-#endif
-#endif
-
#if IN_HEADER(__GDK_FONT_H__)
#if IN_FILE(__GDK_FONT_C__)
#ifndef GDK_DISABLE_DEPRECATED
gdk_display_get_name
gdk_display_get_n_screens
gdk_display_get_screen
-gdk_display_pointer_is_grabbed
gdk_display_pointer_ungrab
gdk_display_keyboard_ungrab
gdk_display_open
#endif
#endif
+#if IN_HEADER(__GDK_WINDOW_H__)
+#if IN_FILE(__GDK_OFFSCREEN_WINDOW_C__)
+gdk_window_set_offscreen_hooks
+gdk_window_get_offscreen_pixmap
+#endif
+#endif
+
#if IN_HEADER(__GDK_WINDOW_H__)
#if IN_FILE(__GDK_DND_X11_C__)
gdk_window_register_dnd
#if IN_HEADER(__GDK_PIXMAP_H__)
#if IN_FILE(__GDK_PIXMAP_C__)
+gdk_bitmap_create_from_data
gdk_pixmap_colormap_create_from_xpm
+gdk_pixmap_create_from_data
gdk_pixmap_create_from_xpm
gdk_pixmap_colormap_create_from_xpm_d
gdk_pixmap_create_from_xpm_d
gdk_pixmap_get_type G_GNUC_CONST
+gdk_pixmap_new
#endif
#endif
#if IN_HEADER(__GDK_PIXMAP_H__)
#if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_pixmap_create_from_data
gdk_pixmap_foreign_new
gdk_pixmap_foreign_new_for_display
gdk_pixmap_foreign_new_for_screen
gdk_pixmap_lookup
gdk_pixmap_lookup_for_display
-gdk_pixmap_new
#endif
#endif
surface = _gdk_drawable_ref_cairo_surface (drawable);
cr = cairo_create (surface);
+
+ if (GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip)
+ GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip (drawable, cr);
+
cairo_surface_destroy (surface);
return cr;
*/
#include "config.h"
+#include <math.h>
#include <glib.h>
#include "gdk.h" /* gdk_event_send_client_message() */
#include "gdkdisplay.h"
+#include "gdkwindowimpl.h"
#include "gdkinternals.h"
#include "gdkmarshalers.h"
#include "gdkscreen.h"
static GdkWindow* singlehead_default_window_at_pointer (GdkScreen *screen,
gint *win_x,
gint *win_y);
+static GdkWindow *gdk_window_real_window_get_pointer (GdkDisplay *display,
+ GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask);
+static GdkWindow *gdk_display_real_get_window_at_pointer (GdkDisplay *display,
+ gint *win_x,
+ gint *win_y);
static guint signals[LAST_SIGNAL] = { 0 };
static const GdkDisplayPointerHooks default_pointer_hooks = {
_gdk_windowing_get_pointer,
- _gdk_windowing_window_get_pointer,
- _gdk_windowing_window_at_pointer
+ gdk_window_real_window_get_pointer,
+ gdk_display_real_get_window_at_pointer
};
static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
*mask = tmp_mask;
}
+static GdkWindow *
+gdk_display_real_get_window_at_pointer (GdkDisplay *display,
+ gint *win_x,
+ gint *win_y)
+{
+ GdkWindow *window;
+ gint x, y;
+
+ window = _gdk_windowing_window_at_pointer (display, &x, &y);
+
+ /* This might need corrections, as the native window returned
+ may contain client side children */
+ if (window)
+ {
+ double xx, yy;
+
+ window = _gdk_window_find_descendant_at (window,
+ x, y,
+ &xx, &yy);
+ x = floor (xx + 0.5);
+ y = floor (yy + 0.5);
+ }
+
+ *win_x = x;
+ *win_y = y;
+
+ return window;
+}
+
+static GdkWindow *
+gdk_window_real_window_get_pointer (GdkDisplay *display,
+ GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
+{
+ GdkWindowObject *private;
+ GdkWindow *pointer_window;
+ gint tmpx, tmpy;
+
+ private = (GdkWindowObject *) window;
+
+ pointer_window = _gdk_windowing_window_get_pointer (display,
+ window,
+ &tmpx, &tmpy,
+ mask);
+ /* We got the coords on the impl, conver to the window */
+ tmpx += private->abs_x;
+ tmpy += private->abs_y;
+
+ if (x)
+ *x = tmpx;
+ if (y)
+ *y = tmpy;
+
+ /* We need to recalculate the true child window with the pointer in it
+ due to possible client side child windows */
+ if (pointer_window != NULL)
+ {
+ /* First get the pointer coords relative to pointer_window */
+ _gdk_windowing_window_get_pointer (display,
+ pointer_window,
+ &tmpx, &tmpy,
+ NULL);
+ /* Then convert that to a client side window */
+ pointer_window = _gdk_window_find_descendant_at (pointer_window,
+ tmpx, tmpy,
+ NULL, NULL);
+ }
+
+ return pointer_window;
+}
+
/**
* gdk_display_get_window_at_pointer:
* @display: a #GdkDisplay
gint *y,
GdkModifierType *mask)
{
- return _gdk_windowing_window_get_pointer (gdk_drawable_get_display (window),
- window, x, y, mask);
+ return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
+ window, x, y, mask);
}
static GdkWindow*
gint *win_x,
gint *win_y)
{
- return _gdk_windowing_window_at_pointer (gdk_screen_get_display (screen),
- win_x, win_y);
+ return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
+ win_x, win_y);
}
/**
return (GdkPointerHooks *)result;
}
+static void
+generate_grab_broken_event (GdkWindow *window,
+ gboolean keyboard,
+ gboolean implicit,
+ GdkWindow *grab_window)
+{
+ g_return_if_fail (window != NULL);
+
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ GdkEvent event;
+ event.type = GDK_GRAB_BROKEN;
+ event.grab_broken.window = window;
+ event.grab_broken.send_event = 0;
+ event.grab_broken.keyboard = keyboard;
+ event.grab_broken.implicit = implicit;
+ event.grab_broken.grab_window = grab_window;
+ gdk_event_put (&event);
+ }
+}
+
+void
+_gdk_display_set_has_pointer_grab (GdkDisplay *display,
+ GdkWindow *window,
+ GdkWindow *native_window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ unsigned long serial,
+ guint32 time,
+ gboolean implicit)
+{
+ int wx, wy;
+
+ /* Normal GRAB events are sent by listening for enter and leave
+ * events on the native event window, which is then proxied
+ * into the virtual windows when the events are seen.
+ * However, there are two cases where X will not send these events:
+ * * When there is already a grab on the native parent of the
+ * virtual grab window
+ * * When there is no grab, but the pointer is already in the
+ * native parent of the virtual grab window
+ * In the first case we send the right GRAB events from the grab, but
+ * in the second case we need to generate our own UNGRAB crossing events.
+ */
+ if (display->pointer_grab.window != NULL &&
+ display->pointer_grab.window != window)
+ {
+ generate_grab_broken_event (GDK_WINDOW (display->pointer_grab.window),
+ FALSE, display->pointer_grab.implicit,
+ window);
+
+ /* Re-grabbing. Pretend we have no grab for now so that
+ the GRAB events get delivered */
+ display->pointer_grab.window = NULL;
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_grab.window,
+ window,
+ GDK_CROSSING_GRAB,
+ /* These may be stale... */
+ display->pointer_info.toplevel_x,
+ display->pointer_info.toplevel_y,
+ display->pointer_info.state,
+ time, TRUE, TRUE);
+ }
+ else if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == native_window)
+ {
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_info.window_under_pointer,
+ window,
+ GDK_CROSSING_GRAB,
+ /* These may be stale... */
+ display->pointer_info.toplevel_x,
+ display->pointer_info.toplevel_y,
+ display->pointer_info.state,
+ time, TRUE, TRUE);
+
+ }
+
+ display->pointer_grab.window = window;
+ display->pointer_grab.native_window = native_window;
+ display->pointer_grab.serial = serial;
+ display->pointer_grab.owner_events = owner_events;
+ display->pointer_grab.event_mask = event_mask;
+ display->pointer_grab.time = time;
+ display->pointer_grab.implicit = implicit;
+ display->pointer_grab.converted_implicit = FALSE;
+}
+
+void
+_gdk_display_unset_has_pointer_grab (GdkDisplay *display,
+ gboolean implicit,
+ gboolean do_grab_one_pointer_release_event,
+ guint32 time)
+{
+ int wx, wy;
+ GdkWindow *old_grab_window;
+ GdkWindow *old_native_grab_window;
+
+
+ old_grab_window = display->pointer_grab.window;
+ old_native_grab_window = display->pointer_grab.native_window;
+
+ if (do_grab_one_pointer_release_event)
+ display->pointer_grab.grab_one_pointer_release_event = display->pointer_grab.window;
+
+ /* We need to set this to null befor syntesizing events to make sure they get
+ delivered to anything but the grab window */
+ display->pointer_grab.window = NULL;
+
+ /* Normal UNGRAB events are sent by listening for enter and leave
+ * events on the native event window, which is then proxied
+ * into the virtual windows when the events are seen.
+ * However, there are two cases where X will not send these events:
+ * * When this ungrab is due to a new grab on the native window that
+ * is a parent of the currently grabbed virtual window
+ * * When there is no new grab, and the pointer is already in the
+ * grabbed virtual windows parent native window
+ * In the first case we send the right GRAB events from the grab, but
+ * in the second case we need to generate our own UNGRAB crossing events.
+ */
+
+ if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == old_native_grab_window)
+ {
+ _gdk_syntesize_crossing_events (display,
+ old_grab_window,
+ display->pointer_info.window_under_pointer,
+ GDK_CROSSING_UNGRAB,
+ /* These may be stale... */
+ display->pointer_info.toplevel_x,
+ display->pointer_info.toplevel_y,
+ display->pointer_info.state,
+ time, TRUE, TRUE);
+ }
+
+ if (implicit)
+ generate_grab_broken_event (old_grab_window,
+ FALSE, implicit,
+ NULL);
+
+}
+
+
+/**
+ * gdk_pointer_grab_info_libgtk_only:
+ * @display: the #GdkDisplay for which to get the grab information
+ * @grab_window: location to store current grab window
+ * @owner_events: location to store boolean indicating whether
+ * the @owner_events flag to gdk_pointer_grab() was %TRUE.
+ *
+ * Determines information about the current pointer grab.
+ * This is not public API and must not be used by applications.
+ *
+ * Return value: %TRUE if this application currently has the
+ * pointer grabbed.
+ **/
+gboolean
+gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
+ GdkWindow **grab_window,
+ gboolean *owner_events)
+{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ if (display->pointer_grab.window)
+ {
+ if (grab_window)
+ *grab_window = (GdkWindow *)display->pointer_grab.window;
+ if (owner_events)
+ *owner_events = display->pointer_grab.owner_events;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+/**
+ * gdk_display_pointer_is_grabbed:
+ * @display: a #GdkDisplay
+ *
+ * Test if the pointer is grabbed.
+ *
+ * Returns: %TRUE if an active X pointer grab is in effect
+ *
+ * Since: 2.2
+ */
+gboolean
+gdk_display_pointer_is_grabbed (GdkDisplay *display)
+{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
+
+ return (display->pointer_grab.window != NULL &&
+ !display->pointer_grab.implicit);
+}
+
#define __GDK_DISPLAY_C__
#include "gdkaliasdef.c"
#define GDK_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY))
#define GDK_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY, GdkDisplayClass))
+/* Tracks information about the pointer grab on this display */
+typedef struct
+{
+ GdkWindow *window;
+ GdkWindow *native_window;
+ gulong serial;
+ gboolean owner_events;
+ guint event_mask;
+ gboolean implicit;
+ gboolean converted_implicit;
+ guint32 time;
+
+ GdkWindow *grab_one_pointer_release_event;
+} GdkPointerGrabInfo;
+
+/* Tracks information about which window the pointer is in and
+ * at what position the mouse is. This is useful when we need
+ * to synthesize events later.
+ */
+typedef struct
+{
+ GdkWindow *window_under_pointer;
+ gdouble toplevel_x, toplevel_y;
+ guint32 state;
+} GdkPointerWindowInfo;
+
struct _GdkDisplay
{
GObject parent_instance;
guint double_click_distance; /* Maximum distance between clicks in pixels */
gint button_x[2]; /* The last 2 button click positions. */
gint button_y[2];
+
+ GdkPointerGrabInfo pointer_grab;
+ GdkPointerWindowInfo pointer_info;
};
struct _GdkDisplayClass
&composite_x_offset,
&composite_y_offset);
+ /* TODO: For non-native windows this may copy stuff from other overlapping
+ windows. We should clip that and clear that area in the destination instead. */
GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
xsrc - composite_x_offset,
cairo_t *cr;
cr = gdk_cairo_create (drawable);
- _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+ _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
if (matrix)
{
g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
cr = gdk_cairo_create (drawable);
- _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+ _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
for (i = 0; i < n_trapezoids; i++)
{
return gdk_drawable_copy_to_image (drawable, NULL, x, y, 0, 0, width, height);
}
-static GdkDrawable*
+static GdkDrawable *
gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
gint x,
gint y,
}
}
+/**
+ * _gdk_drawable_get_source_drawable:
+ * @drawable: a #GdkDrawable
+ *
+ * Returns a drawable for the passed @drawable that is guaranteed to be
+ * usable to create a pixmap (e.g.: not an offscreen window).
+ *
+ * Since: 2.16
+ */
+GdkDrawable *
+_gdk_drawable_get_source_drawable (GdkDrawable *drawable)
+{
+ g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
+
+ if (GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable)
+ return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);
+
+ return drawable;
+}
+
#define __GDK_DRAW_C__
#include "gdkaliasdef.c"
cairo_surface_t *(*ref_cairo_surface) (GdkDrawable *drawable);
+ GdkDrawable *(*get_source_drawable) (GdkDrawable *drawable);
+
+ void (*set_cairo_clip) (GdkDrawable *drawable,
+ cairo_t *cr);
/* Padding for future expansion */
- void (*_gdk_reserved4) (void);
- void (*_gdk_reserved5) (void);
void (*_gdk_reserved6) (void);
void (*_gdk_reserved7) (void);
void (*_gdk_reserved9) (void);
return display->queued_tail;
}
+/**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event after the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_after (GdkDisplay *display,
+ GdkEvent *sibling,
+ GdkEvent *event)
+{
+ GList *prev = g_list_find (display->queued_events, sibling);
+ if (prev && prev->next)
+ {
+ display->queued_events = g_list_insert_before (display->queued_events, prev->next, event);
+ return prev->next;
+ }
+ else
+ return _gdk_event_queue_append (display, event);
+}
+
+/**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event before the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_before (GdkDisplay *display,
+ GdkEvent *sibling,
+ GdkEvent *event)
+{
+ GList *next = g_list_find (display->queued_events, sibling);
+ if (next)
+ {
+ display->queued_events = g_list_insert_before (display->queued_events, next, event);
+ return next->prev;
+ }
+ else
+ return _gdk_event_queue_append (display, event);
+}
+
+
/**
* _gdk_event_queue_remove_link:
* @display: a #GdkDisplay
gint nclicks)
{
GdkEvent temp_event;
+ GdkEvent *event_copy;
+ GList *link;
g_return_if_fail (event != NULL);
temp_event = *event;
temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
-
- gdk_display_put_event (display, &temp_event);
+
+ event_copy = gdk_event_copy (&temp_event);
+ link = _gdk_event_queue_append (display, event_copy);
}
void
GDK_SETTING = 33,
GDK_OWNER_CHANGE = 34,
GDK_GRAB_BROKEN = 35,
- GDK_DAMAGE = 36
+ GDK_DAMAGE = 36,
+ GDK_EVENT_LAST /* helper variable for decls */
} GdkEventType;
/* Event masks. (Used to select what types of events a window
{
GdkRegion *clip_region;
+ GdkSubwindowMode subwindow_mode;
+
GdkFill fill;
GdkBitmap *stipple;
GdkPixmap *tile;
priv->fg_pixel = values->foreground.pixel;
if (values_mask & GDK_GC_BACKGROUND)
priv->bg_pixel = values->background.pixel;
+ if (values_mask & GDK_GC_SUBWINDOW)
+ priv->subwindow_mode = values->subwindow_mode;
gc->colormap = gdk_drawable_get_colormap (drawable);
if (gc->colormap)
{
GdkGC *gc = GDK_GC (object);
GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
-
+
if (priv->clip_region)
gdk_region_destroy (priv->clip_region);
if (gc->colormap)
priv->fg_pixel = values->foreground.pixel;
if (values_mask & GDK_GC_BACKGROUND)
priv->bg_pixel = values->background.pixel;
+ if (values_mask & GDK_GC_SUBWINDOW)
+ priv->subwindow_mode = values->subwindow_mode;
GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
}
gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK);
}
-static void
+/* Takes ownership of passed in region */
+void
_gdk_gc_set_clip_region_internal (GdkGC *gc,
- GdkRegion *region)
+ GdkRegion *region,
+ gboolean reset_origin)
{
GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
priv->clip_region = region;
- _gdk_windowing_gc_set_clip_region (gc, region);
+ _gdk_windowing_gc_set_clip_region (gc, region, reset_origin);
+}
+
+/* Takes ownership of passed in region, returns old clip region */
+void
+_gdk_gc_intersect_clip_region (GdkGC *gc,
+ GdkRegion *region,
+ GdkRegion **old_clip_region)
+{
+ GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+ GdkRegion *old_clip;
+
+ old_clip = priv->clip_region;
+
+ priv->clip_region = region;
+ if (old_clip)
+ gdk_region_intersect (region, old_clip);
+
+ if (old_clip_region)
+ *old_clip_region = old_clip;
+ else
+ gdk_region_destroy (old_clip);
+
+ _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE);
+
+ return old_clip;
}
/**
else
region = NULL;
- _gdk_gc_set_clip_region_internal (gc, region);
+ _gdk_gc_set_clip_region_internal (gc, region, TRUE);
}
/**
else
copy = NULL;
- _gdk_gc_set_clip_region_internal (gc, copy);
+ _gdk_gc_set_clip_region_internal (gc, copy, TRUE);
}
/**
GdkSubwindowMode mode)
{
GdkGCValues values;
+ GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
g_return_if_fail (GDK_IS_GC (gc));
+ /* This could get called a lot to reset the subwindow mode in
+ the client side clipping, so bail out early */
+ if (priv->subwindow_mode == mode)
+ return;
+
values.subwindow_mode = mode;
gdk_gc_set_values (gc, &values, GDK_GC_SUBWINDOW);
}
+GdkSubwindowMode
+_gdk_gc_get_subwindow (GdkGC *gc)
+{
+ GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+ return priv->subwindow_mode;
+}
+
/**
* gdk_gc_set_exposures:
* @gc: a #GdkGC.
dst_priv->fg_pixel = src_priv->fg_pixel;
dst_priv->bg_pixel = src_priv->bg_pixel;
+ dst_priv->subwindow_mode = src_priv->subwindow_mode;
}
/**
* the fill mode will be forced to %GDK_STIPPLED
* @gc_changed: pass %FALSE if the @gc has not changed since the
* last call to this function
+ * @target_drawable: The drawable you're drawing in. If passed in
+ * this is used for client side window clip emulation.
*
* Set the attributes of a cairo context to match those of a #GdkGC
* as far as possible. Some aspects of a #GdkGC, such as clip masks
cairo_t *cr,
const GdkColor *override_foreground,
GdkBitmap *override_stipple,
- gboolean gc_changed)
+ gboolean gc_changed,
+ GdkDrawable *target_drawable)
{
GdkGCPrivate *priv;
GdkFill fill;
cairo_clip (cr);
}
+
+ /* The reset above resets the window clip rect, so we want to re-set that */
+ if (target_drawable && GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip)
+ GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip (target_drawable, cr);
}
void _gdk_events_queue (GdkDisplay *display);
GdkEvent* _gdk_event_unqueue (GdkDisplay *display);
-GList* _gdk_event_queue_find_first (GdkDisplay *display);
-void _gdk_event_queue_remove_link (GdkDisplay *display,
- GList *node);
-GList* _gdk_event_queue_prepend (GdkDisplay *display,
- GdkEvent *event);
-GList* _gdk_event_queue_append (GdkDisplay *display,
- GdkEvent *event);
-void _gdk_event_button_generate (GdkDisplay *display,
- GdkEvent *event);
+GList* _gdk_event_queue_find_first (GdkDisplay *display);
+void _gdk_event_queue_remove_link (GdkDisplay *display,
+ GList *node);
+GList* _gdk_event_queue_prepend (GdkDisplay *display,
+ GdkEvent *event);
+GList* _gdk_event_queue_append (GdkDisplay *display,
+ GdkEvent *event);
+GList* _gdk_event_queue_insert_after (GdkDisplay *display,
+ GdkEvent *after_event,
+ GdkEvent *event);
+GList* _gdk_event_queue_insert_before(GdkDisplay *display,
+ GdkEvent *after_event,
+ GdkEvent *event);
+void _gdk_event_button_generate (GdkDisplay *display,
+ GdkEvent *event);
void _gdk_windowing_event_data_copy (const GdkEvent *src,
GdkEvent *dst);
cairo_surface_t *_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable);
+GdkDrawable *_gdk_drawable_get_source_drawable (GdkDrawable *drawable);
+
/* GC caching */
GdkGC *_gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
gboolean graphics_exposures);
cairo_t *cr,
const GdkColor *override_foreground,
GdkBitmap *override_stipple,
- gboolean gc_changed);
+ gboolean gc_changed,
+ GdkDrawable *target_drawable);
/*************************************
* Interfaces used by windowing code *
*************************************/
-GdkWindow *_gdk_window_new (GdkWindow *window,
- GdkWindowAttr *attributes,
- gint attributes_mask);
-void _gdk_window_destroy (GdkWindow *window,
- gboolean foreign_destroy);
-void _gdk_window_clear_update_area (GdkWindow *window);
-
-void _gdk_screen_close (GdkScreen *screen);
+GdkPixmap *_gdk_pixmap_new (GdkDrawable *drawable,
+ gint width,
+ gint height,
+ gint depth);
+GdkPixmap *_gdk_pixmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ const GdkColor *fg,
+ const GdkColor *bg);
+GdkPixmap *_gdk_bitmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height);
+
+void _gdk_window_impl_new (GdkWindow *window,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkEventMask event_mask,
+ GdkWindowAttr *attributes,
+ gint attributes_mask);
+void _gdk_window_destroy (GdkWindow *window,
+ gboolean foreign_destroy);
+void _gdk_window_clear_update_area (GdkWindow *window);
+void _gdk_window_update_size (GdkWindow *window);
+
+void _gdk_screen_close (GdkScreen *screen);
const char *_gdk_get_sm_client_id (void);
GdkBitmap *_gdk_gc_get_stipple (GdkGC *gc);
guint32 _gdk_gc_get_fg_pixel (GdkGC *gc);
guint32 _gdk_gc_get_bg_pixel (GdkGC *gc);
+void _gdk_gc_intersect_clip_region (GdkGC *gc,
+ GdkRegion *region,
+ GdkRegion **old_region);
+void _gdk_gc_set_clip_region_internal (GdkGC *gc,
+ GdkRegion *region,
+ gboolean reset_origin);
+GdkSubwindowMode _gdk_gc_get_subwindow (GdkGC *gc);
/*****************************************
* Interfaces provided by windowing code *
gint _gdk_windowing_get_bits_for_depth (GdkDisplay *display,
gint depth);
-void _gdk_window_reparent (GdkWindow *window,
- GdkWindow *new_parent,
- gint x,
- gint y);
#define GDK_WINDOW_IS_MAPPED(window) ((((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0)
-/* Called before processing updates for a window. This gives the windowing
- * layer a chance to save the region for later use in avoiding duplicate
- * exposes. The return value indicates whether the function has a saved
- * the region; if the result is TRUE, then the windowing layer is responsible
- * for destroying the region later.
- */
-gboolean _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
- GdkRegion *area);
+void _gdk_windowing_window_queue_translation (GdkWindow *window,
+ GdkRegion *area,
+ gint dx,
+ gint dy);
+
/* Called to do the windowing system specific part of gdk_window_destroy(),
*
* _gdk_windowing_gc_set_clip_region:
* @gc: a #GdkGC
* @region: the new clip region
+ * @reset_origin: if TRUE, reset the clip_x/y_origin values to 0
*
* Do any window-system specific processing necessary
* for a change in clip region. Since the clip origin
* will already return the new region.
**/
void _gdk_windowing_gc_set_clip_region (GdkGC *gc,
- const GdkRegion *region);
+ const GdkRegion *region,
+ gboolean reset_origin);
/**
* _gdk_windowing_gc_copy:
void _gdk_windowing_launch_failed (GAppLaunchContext *context,
const char *startup_notify_id);
+void _gdk_windowing_grab_broken (GdkDisplay *display);
+
+void _gdk_display_set_has_pointer_grab (GdkDisplay *display,
+ GdkWindow *window,
+ GdkWindow *native_window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ unsigned long serial,
+ guint32 time,
+ gboolean implicit);
+void _gdk_display_unset_has_pointer_grab (GdkDisplay *display,
+ gboolean implicit,
+ gboolean do_grab_one_pointer_release_event,
+ guint32 time);
+
+void _gdk_window_invalidate_for_expose (GdkWindow *window,
+ const GdkRegion *region);
+
+void _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+ int width,
+ int height);
+
+cairo_surface_t * _gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height);
+GdkWindow * _gdk_window_find_descendant_at (GdkWindow *toplevel,
+ double x, double y,
+ double *found_x,
+ double *found_y);
+
+void _gdk_window_add_damage (GdkWindow *toplevel,
+ GdkRegion *damaged_region);
+
+GdkEvent * _gdk_make_event (GdkWindow *window,
+ GdkEventType type,
+ GdkEvent *event_in_queue,
+ gboolean before_event);
+
+void _gdk_syntesize_crossing_events (GdkDisplay *display,
+ GdkWindow *src,
+ GdkWindow *dest,
+ GdkCrossingMode mode,
+ gint toplevel_x,
+ gint toplevel_y,
+ GdkModifierType mask,
+ guint32 time_,
+ gboolean do_first,
+ gboolean do_last);
+
+void _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window);
+
+GdkRegion *_gdk_window_calculate_full_clip_region (GdkWindow *window,
+ GdkWindow *base_window,
+ gboolean do_children,
+ gint *base_x_offset,
+ gint *base_y_offset);
+gboolean _gdk_window_has_impl (GdkWindow *window);
+GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
+
+
+/*****************************
+ * offscreen window routines *
+ *****************************/
+GType gdk_offscreen_window_get_type (void);
+void _gdk_offscreen_window_new (GdkWindow *window,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkWindowAttr *attributes,
+ gint attributes_mask);
+void _gdk_offscreen_window_destroy (GdkWindow *window,
+ gboolean recursing);
+
/************************************
* Initialization and exit routines *
--- /dev/null
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2005. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <config.h>
+#include <math.h>
+#include "gdk.h"
+#include "gdkwindow.h"
+#include "gdkinternals.h"
+#include "gdkwindowimpl.h"
+#include "gdkpixmap.h"
+#include "gdkdrawable.h"
+#include "gdktypes.h"
+#include "gdkscreen.h"
+#include "gdkgc.h"
+#include "gdkcolor.h"
+#include "gdkcursor.h"
+#include "gdkalias.h"
+
+/* LIMITATIONS:
+ *
+ * Offscreen windows can't be the child of a foreign window,
+ * nor contain foreign windows
+ *Â GDK_POINTER_MOTION_HINT_MASK isn't effective
+ */
+
+typedef struct _GdkOffscreenWindow GdkOffscreenWindow;
+typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
+
+struct _GdkOffscreenWindow
+{
+ GdkDrawable parent_instance;
+
+ GdkWindow *wrapper;
+ GdkCursor *cursor;
+ GdkColormap *colormap;
+ GdkScreen *screen;
+
+ GdkPixmap *pixmap;
+};
+
+struct _GdkOffscreenWindowClass
+{
+ GdkDrawableClass parent_class;
+};
+
+#define GDK_TYPE_OFFSCREEN_WINDOW (gdk_offscreen_window_get_type())
+#define GDK_OFFSCREEN_WINDOW(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow))
+#define GDK_IS_OFFSCREEN_WINDOW(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+#define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+
+static void gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface);
+static void gdk_offscreen_window_hide (GdkWindow *window);
+static void gdk_offscreen_window_clear_area (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gboolean send_expose);
+
+
+G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow,
+ gdk_offscreen_window,
+ GDK_TYPE_DRAWABLE,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
+ gdk_offscreen_window_impl_iface_init));
+
+
+static void
+gdk_offscreen_window_finalize (GObject *object)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
+
+ if (offscreen->cursor)
+ gdk_cursor_unref (offscreen->cursor);
+
+ offscreen->cursor = NULL;
+
+ gdk_pixmap_unref (offscreen->pixmap);
+
+ G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
+}
+
+static void
+gdk_offscreen_window_init (GdkOffscreenWindow *window)
+{
+}
+
+void
+_gdk_offscreen_window_destroy (GdkWindow *window,
+ gboolean recursing)
+{
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+ GdkOffscreenWindow *offscreen;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ if (!recursing)
+ gdk_offscreen_window_hide (window);
+
+ g_object_unref (offscreen->colormap);
+ offscreen->colormap = NULL;
+}
+
+static gboolean
+is_parent_of (GdkWindow *parent,
+ GdkWindow *child)
+{
+ GdkWindow *w;
+
+ w = child;
+ while (w != NULL)
+ {
+ if (w == parent)
+ return TRUE;
+
+ w = gdk_window_get_parent (w);
+ }
+
+ return FALSE;
+}
+
+static GdkGC *
+gdk_offscreen_window_create_gc (GdkDrawable *drawable,
+ GdkGCValues *values,
+ GdkGCValuesMask values_mask)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return gdk_gc_new_with_values (offscreen->pixmap, values, values_mask);
+}
+
+static GdkImage*
+gdk_offscreen_window_copy_to_image (GdkDrawable *drawable,
+ GdkImage *image,
+ gint src_x,
+ gint src_y,
+ gint dest_x,
+ gint dest_y,
+ gint width,
+ gint height)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return gdk_drawable_copy_to_image (offscreen->pixmap,
+ image,
+ src_x,
+ src_y,
+ dest_x, dest_y,
+ width, height);
+}
+
+static cairo_surface_t *
+gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return _gdk_drawable_ref_cairo_surface (offscreen->pixmap);
+}
+
+static GdkColormap*
+gdk_offscreen_window_get_colormap (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return offscreen->colormap;
+}
+
+static void
+gdk_offscreen_window_set_colormap (GdkDrawable *drawable,
+ GdkColormap*colormap)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ if (colormap && GDK_WINDOW_DESTROYED (offscreen->wrapper))
+ return;
+
+ if (offscreen->colormap == colormap)
+ return;
+
+ if (offscreen->colormap)
+ g_object_unref (offscreen->colormap);
+
+ offscreen->colormap = colormap;
+ if (offscreen->colormap)
+ g_object_ref (offscreen->colormap);
+}
+
+
+static gint
+gdk_offscreen_window_get_depth (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return gdk_drawable_get_depth (offscreen->wrapper);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_source_drawable (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return _gdk_drawable_get_source_drawable (offscreen->pixmap);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_composite_drawable (GdkDrawable *drawable,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint *composite_x_offset,
+ gint *composite_y_offset)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return g_object_ref (offscreen->pixmap);
+}
+
+static GdkScreen*
+gdk_offscreen_window_get_screen (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return offscreen->screen;
+}
+
+static GdkVisual*
+gdk_offscreen_window_get_visual (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return gdk_drawable_get_visual (offscreen->wrapper);
+}
+
+static void
+add_damage (GdkOffscreenWindow *offscreen,
+ int x, int y,
+ int w, int h)
+{
+ GdkRectangle rect;
+ GdkRegion *damage;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = w;
+ rect.height = h;
+
+ damage = gdk_region_rectangle (&rect);
+ _gdk_window_add_damage (offscreen->wrapper, damage);
+ gdk_region_destroy (damage);
+}
+
+static void
+gdk_offscreen_window_draw_drawable (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPixmap *src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+ gdk_draw_drawable (real_drawable, gc,
+ src, xsrc, ysrc,
+ xdest, ydest,
+ width, height);
+
+ add_damage (offscreen, xdest, ydest, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_rectangle (GdkDrawable *drawable,
+ GdkGC *gc,
+ gboolean filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+ gdk_draw_rectangle (real_drawable,
+ gc, filled, x, y, width, height);
+
+ add_damage (offscreen, x, y, width, height);
+
+}
+
+static void
+gdk_offscreen_window_draw_arc (GdkDrawable *drawable,
+ GdkGC *gc,
+ gboolean filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint angle1,
+ gint angle2)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+ gdk_draw_arc (real_drawable,
+ gc,
+ filled,
+ x,
+ y,
+ width,
+ height,
+ angle1,
+ angle2);
+ add_damage (offscreen, x, y, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_polygon (GdkDrawable *drawable,
+ GdkGC *gc,
+ gboolean filled,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+ gdk_draw_polygon (real_drawable,
+ gc,
+ filled,
+ points,
+ npoints);
+
+ if (npoints > 0)
+ {
+ int min_x, min_y, max_x, max_y, i;
+
+ min_x = max_x = points[0].x;
+ min_y = max_y = points[0].y;
+
+ for (i = 1; i < npoints; i++)
+ {
+ min_x = MIN (min_x, points[i].x);
+ max_x = MAX (max_x, points[i].x);
+ min_y = MIN (min_y, points[i].y);
+ max_y = MAX (max_y, points[i].y);
+ }
+
+ add_damage (offscreen, min_x, min_y,
+ max_x - min_x,
+ max_y - min_y);
+ }
+}
+
+static void
+gdk_offscreen_window_draw_text (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *text,
+ gint text_length)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+ gdk_draw_text (real_drawable,
+ font,
+ gc,
+ x,
+ y,
+ text,
+ text_length);
+
+ /* Hard to compute the minimal size, not that often used anyway. */
+ add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_text_wc (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const GdkWChar *text,
+ gint text_length)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+ gdk_draw_text_wc (real_drawable,
+ font,
+ gc,
+ x,
+ y,
+ text,
+ text_length);
+
+ /* Hard to compute the minimal size, not that often used anyway. */
+ add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_points (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+ gdk_draw_points (real_drawable,
+ gc,
+ points,
+ npoints);
+
+
+ if (npoints > 0)
+ {
+ int min_x, min_y, max_x, max_y, i;
+
+ min_x = max_x = points[0].x;
+ min_y = max_y = points[0].y;
+
+ for (i = 1; i < npoints; i++)
+ {
+ min_x = MIN (min_x, points[i].x);
+ max_x = MAX (max_x, points[i].x);
+ min_y = MIN (min_y, points[i].y);
+ max_y = MAX (max_y, points[i].y);
+ }
+
+ add_damage (offscreen, min_x, min_y,
+ max_x - min_x,
+ max_y - min_y);
+ }
+}
+
+static void
+gdk_offscreen_window_draw_segments (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkSegment *segs,
+ gint nsegs)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+ gdk_draw_segments (real_drawable,
+ gc,
+ segs,
+ nsegs);
+
+ if (nsegs > 0)
+ {
+ int min_x, min_y, max_x, max_y, i;
+
+ min_x = max_x = segs[0].x1;
+ min_y = max_y = segs[0].y1;
+
+ for (i = 1; i < nsegs; i++)
+ {
+ min_x = MIN (min_x, segs[i].x1);
+ max_x = MAX (max_x, segs[i].x1);
+ min_x = MIN (min_x, segs[i].x2);
+ max_x = MAX (max_x, segs[i].x2);
+ min_y = MIN (min_y, segs[i].y1);
+ max_y = MAX (max_y, segs[i].y1);
+ min_y = MIN (min_y, segs[i].y2);
+ max_y = MAX (max_y, segs[i].y2);
+ }
+
+ add_damage (offscreen, min_x, min_y,
+ max_x - min_x,
+ max_y - min_y);
+ }
+
+}
+
+static void
+gdk_offscreen_window_draw_lines (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+ gdk_draw_lines (real_drawable,
+ gc,
+ points,
+ npoints);
+
+ /* Hard to compute the minimal size, as we don't know the line
+ width, and since joins are hard to calculate.
+ Its not that often used anyway, damage it all */
+ add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_image (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+ gdk_draw_image (real_drawable,
+ gc,
+ image,
+ xsrc,
+ ysrc,
+ xdest,
+ ydest,
+ width,
+ height);
+
+ add_damage (offscreen, xdest, ydest, width, height);
+}
+
+
+static void
+gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPixbuf *pixbuf,
+ gint src_x,
+ gint src_y,
+ gint dest_x,
+ gint dest_y,
+ gint width,
+ gint height,
+ GdkRgbDither dither,
+ gint x_dither,
+ gint y_dither)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+ gdk_draw_pixbuf (real_drawable,
+ gc,
+ pixbuf,
+ src_x,
+ src_y,
+ dest_x,
+ dest_y,
+ width,
+ height,
+ dither,
+ x_dither,
+ y_dither);
+
+ add_damage (offscreen, dest_x, dest_y, width, height);
+
+}
+
+void
+_gdk_offscreen_window_new (GdkWindow *window,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
+{
+ GdkWindowObject *parent_private;
+ GdkWindowObject *private;
+ GdkOffscreenWindow *offscreen;
+
+ g_return_if_fail (attributes != NULL);
+
+ if (attributes->wclass != GDK_INPUT_OUTPUT)
+ return; /* Can't support input only offscreens */
+
+ private = (GdkWindowObject *)window;
+
+ if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent))
+ return;
+
+ parent_private = (GdkWindowObject*) private->parent;
+ private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+ offscreen->wrapper = window;
+
+ offscreen->screen = screen;
+
+ if (attributes_mask & GDK_WA_COLORMAP)
+ offscreen->colormap = g_object_ref (attributes->colormap);
+ else
+ {
+ if (gdk_screen_get_system_visual (screen) == visual)
+ {
+ offscreen->colormap = gdk_screen_get_system_colormap (screen);
+ g_object_ref (offscreen->colormap);
+ }
+ else
+ offscreen->colormap = gdk_colormap_new (visual, FALSE);
+ }
+
+ offscreen->pixmap = gdk_pixmap_new ((GdkDrawable *)private->parent,
+ private->width,
+ private->height,
+ private->depth);
+}
+
+static gboolean
+gdk_offscreen_window_reparent (GdkWindow *window,
+ GdkWindow *new_parent,
+ gint x,
+ gint y)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent;
+ GdkWindowObject *old_parent;
+ GdkOffscreenWindow *offscreen;
+ gboolean was_mapped;
+
+ if (new_parent)
+ {
+ /* No input-output children of input-only windows */
+ if (new_parent_private->input_only && !private->input_only)
+ return FALSE;
+
+ /* Don't create loops in hierarchy */
+ if (is_parent_of (window, new_parent))
+ return FALSE;
+ }
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ was_mapped = GDK_WINDOW_IS_MAPPED (window);
+
+ gdk_window_hide (window);
+
+ if (private->parent)
+ private->parent->children = g_list_remove (private->parent->children, window);
+
+ old_parent = private->parent;
+ private->parent = new_parent_private;
+ private->x = x;
+ private->y = y;
+
+ if (new_parent_private)
+ private->parent->children = g_list_prepend (private->parent->children, window);
+
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+ if (old_parent)
+ _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent));
+
+ return was_mapped;
+}
+
+static gint
+gdk_offscreen_window_get_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ if (x)
+ *x = 0;
+ if (y)
+ *y = 0;
+
+ return TRUE;
+}
+
+/**
+ * gdk_window_get_offscreen_pixmap:
+ * @window: a #GdkWindow
+ *
+ * Gets the offscreen pixmap that an offscreen window renders into. If
+ * you need to keep this around over window resizes, you need to add a
+ * reference to it.
+ *
+ * Returns: The offscreen pixmap, or NULL if not offscreen
+ **/
+GdkPixmap *
+gdk_window_get_offscreen_pixmap (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+ if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
+ return NULL;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+ return offscreen->pixmap;
+}
+
+static void
+gdk_offscreen_window_raise (GdkWindow *window)
+{
+ /* gdk_window_raise already changed the stacking order */
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_lower (GdkWindow *window)
+{
+ /* gdk_window_lower already changed the stacking order */
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_move_resize_internal (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gboolean send_expose_events)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+ gint dx, dy, dw, dh;
+ GdkGC *gc;
+ GdkPixmap *old_pixmap;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ if (private->destroyed)
+ return;
+
+ dx = x - private->x;
+ dy = y - private->y;
+ dw = width - private->width;
+ dh = height - private->height;
+
+ private->x = x;
+ private->y = y;
+
+ if (private->width != width ||
+ private->height != height)
+ {
+ private->width = width;
+ private->height = height;
+
+ old_pixmap = offscreen->pixmap;
+ offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
+ width,
+ height,
+ private->depth);
+
+ gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE);
+ gdk_draw_drawable (offscreen->pixmap,
+ gc,
+ old_pixmap,
+ 0,0, 0, 0,
+ -1, -1);
+ g_object_unref (old_pixmap);
+ }
+
+ if (GDK_WINDOW_IS_MAPPED (private))
+ {
+ // TODO: Only invalidate new area, i.e. for larger windows
+ gdk_window_invalidate_rect (window, NULL, TRUE);
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+ }
+}
+
+static void
+gdk_offscreen_window_move_resize (GdkWindow *window,
+ gboolean with_move,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ if (!with_move)
+ {
+ x = private->x;
+ y = private->y;
+ }
+
+ if (width < 0)
+ width = private->width;
+
+ if (height < 0)
+ height = private->height;
+
+ gdk_offscreen_window_move_resize_internal (window, x, y,
+ width, height,
+ TRUE);
+}
+
+static void
+gdk_offscreen_window_show (GdkWindow *window, gboolean raise)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ return;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ private->state = 0;
+
+ /* gdk_window_show already changed the stacking order if needed */
+
+ if (private->event_mask & GDK_STRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+
+ if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+
+ if (gdk_window_is_viewable (window))
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+
+ gdk_window_clear_area_e (window, 0, 0,
+ private->width, private->height);
+}
+
+
+static void
+gdk_offscreen_window_hide (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ GdkOffscreenWindow *offscreen;
+ GdkDisplay *display;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowObject*) window;
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ if (!GDK_WINDOW_IS_MAPPED (private))
+ return;
+
+ /* May need to break grabs on children */
+ display = gdk_drawable_get_display (window);
+
+ if (display->pointer_grab.window != NULL)
+ {
+ if (is_parent_of (window, display->pointer_grab.window))
+ {
+ /* Call this ourselves, even though gdk_display_pointer_ungrab
+ does so too, since we want to pass implicit == TRUE so the
+ broken grab event is generated */
+ _gdk_display_unset_has_pointer_grab (display,
+ TRUE,
+ FALSE,
+ GDK_CURRENT_TIME);
+ gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+ }
+ }
+
+ if (private->event_mask & GDK_STRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+ if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+ private->state = GDK_WINDOW_STATE_WITHDRAWN;
+
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_withdraw (GdkWindow *window)
+{
+}
+
+static GdkEventMask
+gdk_offscreen_window_get_events (GdkWindow *window)
+{
+ return 0;
+}
+
+static void
+gdk_offscreen_window_set_events (GdkWindow *window,
+ GdkEventMask event_mask)
+{
+}
+
+static GdkGC *
+setup_backing_rect_gc (GdkWindow *window, int x_offset, int y_offset)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkGC *gc;
+
+ if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+ {
+ x_offset += private->x;
+ y_offset += private->y;
+
+ return setup_backing_rect_gc (GDK_WINDOW (private->parent), x_offset, y_offset);
+ }
+ else if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ {
+ guint gc_mask;
+ GdkGCValues gc_values;
+
+ gc_values.fill = GDK_TILED;
+ gc_values.tile = private->bg_pixmap;
+ gc_values.ts_x_origin = -x_offset;
+ gc_values.ts_y_origin = -y_offset;
+
+ gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
+
+ return gdk_gc_new_with_values (window, &gc_values, gc_mask);
+ }
+ else
+ {
+ gc = _gdk_drawable_get_scratch_gc (window, FALSE);
+ g_object_ref (gc);
+ gdk_gc_set_foreground (gc, &private->bg_color);
+ return gc;
+ }
+}
+
+static void
+gdk_offscreen_window_clear_area (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gboolean send_expose)
+{
+ GdkGC *gc;
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ /* Actual drawing is done by gdkwindow.c */
+
+ gc = setup_backing_rect_gc (window, 0, 0);
+ gdk_draw_rectangle (window, gc, TRUE, x, y, width, height);
+ g_object_unref (gc);
+
+ if (send_expose)
+ {
+ GdkRectangle visible, rect;
+
+ visible.x = visible.y = 0;
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &visible.width, &visible.height);
+
+ rect.x = x;
+ rect.y = x;
+ rect.width = width;
+ rect.height = height;
+
+ gdk_rectangle_intersect (&rect, &visible, &rect);
+
+ gdk_window_invalidate_rect (window, &rect, TRUE);
+ }
+}
+
+static void
+gdk_offscreen_window_set_background (GdkWindow *window,
+ const GdkColor *color)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkColormap *colormap = gdk_drawable_get_colormap (window);
+
+ private->bg_color = *color;
+ gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+ if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_unref (private->bg_pixmap);
+
+ private->bg_pixmap = NULL;
+}
+
+static void
+gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
+ GdkPixmap *pixmap)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG &&
+ !gdk_drawable_get_colormap (pixmap))
+ {
+ g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+ return;
+ }
+
+ if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_unref (private->bg_pixmap);
+
+ private->bg_pixmap = pixmap;
+
+ if (pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_ref (pixmap);
+}
+
+static void
+gdk_offscreen_window_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x,
+ gint y)
+{
+}
+
+static void
+gdk_offscreen_window_shape_combine_region (GdkWindow *window,
+ const GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
+{
+}
+
+static void
+gdk_offscreen_window_set_child_shapes (GdkWindow *window)
+{
+}
+
+static void
+gdk_offscreen_window_merge_child_shapes (GdkWindow *window)
+{
+}
+
+static gboolean
+gdk_offscreen_window_set_static_gravities (GdkWindow *window,
+ gboolean use_static)
+{
+ return TRUE;
+}
+
+static void
+gdk_offscreen_window_set_cursor (GdkWindow *window,
+ GdkCursor *cursor)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ if (offscreen->cursor)
+ {
+ gdk_cursor_unref (offscreen->cursor);
+ offscreen->cursor = NULL;
+ }
+
+ if (cursor)
+ offscreen->cursor = gdk_cursor_ref (cursor);
+
+ /* TODO: The cursor is never actually used... */
+}
+
+static void
+gdk_offscreen_window_get_geometry (GdkWindow *window,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ gint *depth)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ if (x)
+ *x = private->x;
+ if (y)
+ *y = private->y;
+ if (width)
+ *width = private->width;
+ if (height)
+ *height = private->height;
+ if (depth)
+ *depth = private->depth;
+ }
+}
+
+/**
+ * gdk_window_set_offscreen_hooks:
+ * @offscreen_window: a offscreen #GdkWindow
+ * @hooks: a table of pointers to functions for handling offscreen
+ * window coordinates translations
+ *
+ * Sets the parent-to-offscreen-child and offscreen-child-to-parent coordinate
+ * translation functions for offscreen windows.
+ *
+ * This function is useful for complex widgets employing
+ * offscreen windows.
+ *
+ * Since: 2.16
+ */
+void
+gdk_window_set_offscreen_hooks (GdkWindow *offscreen_window,
+ const GdkOffscreenChildHooks *hooks)
+{
+ GdkWindowObject *private;
+
+ g_return_if_fail (GDK_IS_WINDOW (offscreen_window));
+ g_return_if_fail (hooks != NULL);
+
+ private = (GdkWindowObject *) offscreen_window;
+
+ private->offscreen_hooks = hooks;
+}
+
+static gboolean
+gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
+ GdkRegion *area)
+{
+ return FALSE;
+}
+
+static void
+gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
+{
+ GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gdk_offscreen_window_finalize;
+
+ drawable_class->create_gc = gdk_offscreen_window_create_gc;
+ drawable_class->_copy_to_image = gdk_offscreen_window_copy_to_image;
+ drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
+ drawable_class->set_colormap = gdk_offscreen_window_set_colormap;
+ drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
+ drawable_class->get_depth = gdk_offscreen_window_get_depth;
+ drawable_class->get_screen = gdk_offscreen_window_get_screen;
+ drawable_class->get_visual = gdk_offscreen_window_get_visual;
+ drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable;
+ drawable_class->get_composite_drawable = gdk_offscreen_window_get_composite_drawable;
+
+ drawable_class->draw_rectangle = gdk_offscreen_window_draw_rectangle;
+ drawable_class->draw_arc = gdk_offscreen_window_draw_arc;
+ drawable_class->draw_polygon = gdk_offscreen_window_draw_polygon;
+ drawable_class->draw_text = gdk_offscreen_window_draw_text;
+ drawable_class->draw_text_wc = gdk_offscreen_window_draw_text_wc;
+ drawable_class->draw_drawable = gdk_offscreen_window_draw_drawable;
+ drawable_class->draw_points = gdk_offscreen_window_draw_points;
+ drawable_class->draw_segments = gdk_offscreen_window_draw_segments;
+ drawable_class->draw_lines = gdk_offscreen_window_draw_lines;
+ drawable_class->draw_image = gdk_offscreen_window_draw_image;
+ drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf;
+}
+
+static void
+gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
+{
+ iface->show = gdk_offscreen_window_show;
+ iface->hide = gdk_offscreen_window_hide;
+ iface->withdraw = gdk_offscreen_window_withdraw;
+ iface->raise = gdk_offscreen_window_raise;
+ iface->lower = gdk_offscreen_window_lower;
+ iface->move_resize = gdk_offscreen_window_move_resize;
+ iface->set_background = gdk_offscreen_window_set_background;
+ iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap;
+ iface->get_events = gdk_offscreen_window_get_events;
+ iface->set_events = gdk_offscreen_window_set_events;
+ iface->clear_area = gdk_offscreen_window_clear_area;
+ iface->reparent = gdk_offscreen_window_reparent;
+ iface->set_cursor = gdk_offscreen_window_set_cursor;
+ iface->get_geometry = gdk_offscreen_window_get_geometry;
+ iface->shape_combine_mask = gdk_offscreen_window_shape_combine_mask;
+ iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
+ iface->set_child_shapes = gdk_offscreen_window_set_child_shapes;
+ iface->merge_child_shapes = gdk_offscreen_window_merge_child_shapes;
+ iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
+ iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
+ iface->get_origin = gdk_offscreen_window_get_origin;
+}
+
+#define __GDK_OFFSCREEN_WINDOW_C__
+#include "gdkaliasdef.c"
priv->cr,
color,
priv->stipple[part],
- priv->gc_changed);
+ priv->gc_changed,
+ priv->drawable);
}
priv->last_part = part;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+GdkPixmap *
+gdk_pixmap_new (GdkDrawable *drawable,
+ gint width,
+ gint height,
+ gint depth)
+{
+ GdkDrawable *source_drawable;
+
+ source_drawable = _gdk_drawable_get_source_drawable (drawable);
+ return _gdk_pixmap_new (source_drawable, width, height, depth);
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height)
+{
+ GdkDrawable *source_drawable;
+
+ source_drawable = _gdk_drawable_get_source_drawable (drawable);
+ return _gdk_bitmap_create_from_data (source_drawable, data, width, height);
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ const GdkColor *fg,
+ const GdkColor *bg)
+{
+ GdkDrawable *source_drawable;
+
+ source_drawable = _gdk_drawable_get_source_drawable (drawable);
+ return _gdk_pixmap_create_from_data (source_drawable,
+ data, width, height,
+ depth, fg,bg);
+}
+
+
static GdkGC *
gdk_pixmap_create_gc (GdkDrawable *drawable,
GdkGCValues *values,
#include "gdkscreen.h"
#include "gdkalias.h"
-#define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h" /* For workaround */
+#endif
+
+#include "math.h"
+
+/* Not all GdkWindows have a corresponding native window.
+ * Instead some draw into the nearest parent that has whatss
+ * called an "impl", i.e. the implementation window.
+ * For toplevel window system windows the impl is always native
+ * window, but child windows can also have native windows as
+ * this is sometimes necessary. Furthermore, offscreen windows
+ * (type GDK_WINDOW_OFFSCREEN) have an impl of type
+ * GdkOffscreenWindow rather than a backend implementation native
+ * window. Such windows draw into an offscreen pixmap instead
+ * of a window and collect damage that lets you paint it where
+ * you want.
+ *
+ * All GdkWindow track their position, size, clip region and
+ * absolute position in the impl window. For child window with
+ * native windows the clip region is set on the native window
+ * as a window shape to make it clip against other non-native windows.
+ */
-typedef struct _GdkWindowPaint GdkWindowPaint;
+#define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
struct _GdkWindowPaint
{
gint x_offset;
gint y_offset;
cairo_surface_t *surface;
+ guint uses_implicit : 1;
};
-typedef struct {
- GdkRegion *old_region;
- gint old_clip_x_origin;
- gint old_clip_y_origin;
- gint x_offset;
- gint y_offset;
-} GdkWindowClipData;
-
-struct _GdkWindowRedirect
-{
- GdkWindowObject *redirected;
- GdkDrawable *pixmap;
- gint src_x;
- gint src_y;
- gint dest_x;
- gint dest_y;
- gint width;
- gint height;
-};
+/* Global info */
static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
GdkGCValues *values,
gint height);
static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
+static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
+ cairo_t *cr);
static void gdk_window_real_get_size (GdkDrawable *drawable,
gint *width,
GdkColormap *cmap);
static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
+static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
gint x,
gint y,
gint y,
gint width,
gint height);
-static void setup_redirect_clip (GdkWindow *window,
- GdkGC *gc,
- GdkWindowClipData *data);
-static void reset_redirect_clip (GdkWindow *offscreen,
- GdkGC *gc,
- GdkWindowClipData *data);
static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
static void apply_redirect_to_children (GdkWindowObject *private,
GdkWindowRedirect *redirect);
static void remove_redirect_from_children (GdkWindowObject *private,
GdkWindowRedirect *redirect);
-static GdkRegion *_gdk_window_calculate_full_clip_region (GdkWindow *window,
- GdkWindow *base_window,
- GdkGC *gc,
- gboolean do_children,
- gint *base_x_offset,
- gint *base_y_offset);
+static void recompute_visible_regions (GdkWindowObject *private,
+ gboolean recalculate_siblings,
+ gboolean recalculate_children);
+
static gpointer parent_class = NULL;
+static const cairo_user_data_key_t gdk_window_cairo_key;
+
GType
gdk_window_object_get_type (void)
{
window->window_type = GDK_WINDOW_CHILD;
window->state = GDK_WINDOW_STATE_WITHDRAWN;
+ window->width = 1;
+ window->height = 1;
+ window->toplevel_window_type = -1;
}
static GQuark quark_pointer_window = 0;
drawable_class->get_visual = gdk_window_real_get_visual;
drawable_class->_copy_to_image = gdk_window_copy_to_image;
drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
+ drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
drawable_class->get_clip_region = gdk_window_get_clip_region;
drawable_class->get_visible_region = gdk_window_get_visible_region;
drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
+ drawable_class->get_source_drawable = gdk_window_get_source_drawable;
quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
}
_gdk_window_destroy (window, TRUE);
}
- g_object_unref (obj->impl);
- obj->impl = NULL;
+ if (obj->impl)
+ {
+ g_object_unref (obj->impl);
+ obj->impl = NULL;
+ }
+
+ if (obj->cursor)
+ gdk_cursor_unref (obj->cursor);
+
+ if (obj->colormap)
+ g_object_unref (obj->colormap);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+static gboolean
+gdk_window_is_offscreen (GdkWindowObject *window)
+{
+ return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
+}
+
+static GdkWindowObject *
+gdk_window_get_impl_window (GdkWindowObject *window)
+{
+ while (window->parent->impl == window->impl)
+ window = window->parent;
+
+ return window;
+}
+
+GdkWindow *
+_gdk_window_get_impl_window (GdkWindow *window)
+{
+ return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_impl (GdkWindowObject *window)
+{
+ return window->parent == NULL || window->parent->impl != window->impl;
+}
+
+gboolean
+_gdk_window_has_impl (GdkWindow *window)
+{
+ return gdk_window_has_impl ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_no_impl (GdkWindowObject *window)
+{
+ return window->parent->impl == window->impl;
+}
+
+static void
+remove_child_area (GdkWindowObject *private,
+ GdkWindowObject *until,
+ GdkRegion *region)
+{
+ GdkWindowObject *child;
+ GdkRegion *child_region;
+ GdkRectangle r;
+ GList *l;
+
+ for (l = private->children; l; l = l->next)
+ {
+ child = l->data;
+
+ if (child == until)
+ break;
+
+ if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
+ continue;
+
+ /* Ignore offscreen children, as they don't draw in their parent and
+ * don't take part in the clipping */
+ if (gdk_window_is_offscreen (child))
+ continue;
+
+ r.x = child->x;
+ r.y = child->y;
+ r.width = child->width;
+ r.height = child->height;
+
+ child_region = gdk_region_rectangle (&r);
+ gdk_region_subtract (region, child_region);
+ gdk_region_destroy (child_region);
+ }
+}
+
+static void
+recompute_visible_regions_internal (GdkWindowObject *private,
+ gboolean recalculate_clip,
+ gboolean recalculate_siblings,
+ gboolean recalculate_children)
+{
+ GdkRectangle r;
+ GList *l;
+ GdkWindowObject *child;
+ GdkRegion *new_clip;
+ gboolean clip_region_changed;
+ gboolean abs_pos_changed;
+ int old_abs_x, old_abs_y;
+
+ old_abs_x = private->abs_x;
+ old_abs_y = private->abs_y;
+
+ /* Update absolute position */
+ if (gdk_window_has_impl (private))
+ {
+ /* Native window starts here */
+ private->abs_x = 0;
+ private->abs_y = 0;
+ }
+ else
+ {
+ private->abs_x = private->parent->abs_x + private->x;
+ private->abs_y = private->parent->abs_y + private->y;
+ }
+
+ abs_pos_changed =
+ private->abs_x != old_abs_x ||
+ private->abs_y != old_abs_y;
+
+ /* Update clip region based on:
+ * parent clip
+ * window size
+ * siblings in parents above window
+ */
+ clip_region_changed = FALSE;
+ if (recalculate_clip)
+ {
+ /* Calculate visible region (sans children) in parent window coords */
+ r.x = private->x;
+ r.y = private->y;
+ r.width = private->width;
+ r.height = private->height;
+ new_clip = gdk_region_rectangle (&r);
+
+ if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+ {
+ gdk_region_intersect (new_clip, private->parent->clip_region);
+
+ /* Remove all overlapping children from parent */
+ remove_child_area (private->parent, private, new_clip);
+ }
+
+ /* Convert from parent coords to window coords */
+ gdk_region_offset (new_clip, -private->x, -private->y);
+
+ if (private->clip_region == NULL ||
+ !gdk_region_equal (private->clip_region, new_clip))
+ clip_region_changed = TRUE;
+
+ if (private->clip_region)
+ gdk_region_destroy (private->clip_region);
+ private->clip_region = new_clip;
+
+ private->clip_region_with_children = gdk_region_copy (private->clip_region);
+ remove_child_area (private, NULL, private->clip_region_with_children);
+ }
+
+ /* Update all children, recursively. */
+ if (abs_pos_changed || clip_region_changed || recalculate_children)
+ {
+ for (l = private->children; l; l = l->next)
+ {
+ child = l->data;
+ /* Only recalculate clip if the the clip region changed, otherwise
+ * there is no way the child clip region could change (its has not e.g. moved)
+ * Except if recalculate_children is set to force child updates
+ */
+ recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
+ }
+ }
+
+ if (clip_region_changed &&
+ gdk_window_has_impl (private) &&
+ /* Not for offscreens */
+ private->window_type != GDK_WINDOW_OFFSCREEN &&
+ /* or for toplevels */
+ private->parent != NULL &&
+ GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT
+ )
+ {
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
+ }
+
+
+ if (recalculate_siblings &&
+ private->parent != NULL &&
+ GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+ {
+ /* If we moved a child window in parent or changed the stacking order, then we
+ * need to recompute the visible area of all the other children in the parent
+ */
+ for (l = private->parent->children; l; l = l->next)
+ {
+ child = l->data;
+
+ if (child != private)
+ recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
+ }
+
+ /* We also need to recompute the _with_children clip for the parent */
+ recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
+ }
+
+ if (private->cairo_surface)
+ {
+ int width, height;
+
+ /* It would be nice if we had some cairo support here so we
+ could set the clip rect on the cairo surface */
+ width = private->abs_x + private->width;
+ height = private->abs_y + private->height;
+
+ _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
+ width, height);
+ cairo_surface_set_device_offset (private->cairo_surface,
+ private->abs_x,
+ private->abs_y);
+ }
+}
+
+/* Call this when private has changed in one or more of these ways:
+ * size changed
+ * window moved
+ * new window added
+ * stacking order of window changed
+ * child deleted
+ *
+ * It will recalculate abs_x/y and the clip regions
+ *
+ * Unless the window didn't change stacking order or size/pos, pass in TRUE
+ * for recalculate_siblings. (Mostly used internally for the recursion)
+ *
+ * If a child window was removed (and you can't use that child for
+ * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
+ */
+static void
+recompute_visible_regions (GdkWindowObject *private,
+ gboolean recalculate_siblings,
+ gboolean recalculate_children)
+{
+ recompute_visible_regions_internal (private,
+ TRUE,
+ recalculate_siblings,
+ recalculate_children);
+}
+
+void
+_gdk_window_update_size (GdkWindow *window)
+{
+ recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
+}
+
+
/**
* gdk_window_new:
* @parent: a #GdkWindow, or %NULL to create the window as a child of
gint attributes_mask)
{
GdkWindow *window;
- GdkWindowObject *private, *parent_private;
-
- g_return_val_if_fail (parent == NULL || GDK_IS_WINDOW (parent), NULL);
+ GdkWindowObject *private;
+ GdkScreen *screen;
+ GdkVisual *visual;
+ int x, y, depth;
+ gboolean native;
+ GdkEventMask event_mask;
+
g_return_val_if_fail (attributes != NULL, NULL);
+
+ if (!parent)
+ {
+ GDK_NOTE (MULTIHEAD,
+ g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
+
+ screen = gdk_screen_get_default ();
+ parent = gdk_screen_get_root_window (screen);
+ }
+ else
+ screen = gdk_drawable_get_screen (parent);
+
+ g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
+
+ if (GDK_WINDOW_DESTROYED (parent))
+ return NULL;
+
+ window = g_object_new (GDK_TYPE_WINDOW, NULL);
+ private = (GdkWindowObject *) window;
- window = _gdk_window_new (parent, attributes, attributes_mask);
- g_return_val_if_fail (window != NULL, window);
+ /* Windows with a foreign parent are treated as if they are children
+ * of the root window, except for actual creation.
+ */
+ if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
+ parent = gdk_screen_get_root_window (screen);
+
+ private->parent = (GdkWindowObject *)parent;
+
+ private->accept_focus = TRUE;
+ private->focus_on_map = TRUE;
+
+ if (attributes_mask & GDK_WA_X)
+ x = attributes->x;
+ else
+ x = 0;
+
+ if (attributes_mask & GDK_WA_Y)
+ y = attributes->y;
+ else
+ y = 0;
+
+ private->x = x;
+ private->y = y;
+ private->width = (attributes->width > 1) ? (attributes->width) : (1);
+ private->height = (attributes->height > 1) ? (attributes->height) : (1);
+
+#ifdef GDK_WINDOWING_X11
+ /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
+ * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
+ */
+ if (attributes->wclass == GDK_INPUT_ONLY &&
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
+ !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
+ {
+ g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
+ attributes->wclass = GDK_INPUT_OUTPUT;
+ }
+#endif
+
+ if (attributes->wclass == GDK_INPUT_ONLY)
+ {
+ /* Backwards compatiblity - we've always ignored
+ * attributes->window_type for input-only windows
+ * before
+ */
+ if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
+ private->window_type = GDK_WINDOW_TEMP;
+ else
+ private->window_type = GDK_WINDOW_CHILD;
+ }
+ else
+ private->window_type = attributes->window_type;
+
+ /* Sanity checks */
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+ g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
+ "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+ case GDK_WINDOW_CHILD:
+ case GDK_WINDOW_OFFSCREEN:
+ break;
+ default:
+ g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
+ return NULL;
+ }
+
+ if (attributes_mask & GDK_WA_VISUAL)
+ visual = attributes->visual;
+ else
+ visual = gdk_screen_get_system_visual (screen);
+
+ private->event_mask = attributes->event_mask;
+
+ if (attributes->wclass == GDK_INPUT_OUTPUT)
+ {
+ depth = visual->depth;
- /* Inherit redirection from parent */
- if (parent != NULL)
+ if (attributes_mask & GDK_WA_COLORMAP)
+ private->colormap = g_object_ref (attributes->colormap);
+
+ private->input_only = FALSE;
+ private->depth = depth;
+
+ private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
+ private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
+
+ private->bg_pixmap = NULL;
+ }
+ else
+ {
+ depth = 0;
+ private->depth = 0;
+ private->input_only = TRUE;
+ }
+
+ if (private->parent)
+ private->parent->children = g_list_prepend (private->parent->children, window);
+
+ native = FALSE; /* Default */
+ if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ native = TRUE; /* Always use native windows for toplevels */
+
+ if (private->window_type == GDK_WINDOW_OFFSCREEN)
+ {
+ _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
+ }
+ else if (native)
+ {
+ if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ event_mask =
+ GDK_EXPOSURE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+ GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK |
+ GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SCROLL_MASK;
+ else
+ event_mask = GDK_EXPOSURE_MASK;
+
+ /* Create the impl */
+ _gdk_window_impl_new (window, screen, visual, event_mask, attributes, attributes_mask);
+ }
+ else
{
- parent_private = GDK_WINDOW_OBJECT (parent);
- private = GDK_WINDOW_OBJECT (window);
- private->redirect = parent_private->redirect;
+ private->impl = private->parent->impl;
}
+
+ recompute_visible_regions (private, TRUE, FALSE);
+ if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+ {
+ /* Inherit redirection from parent */
+ private->redirect = private->parent->redirect;
+ }
+
return window;
}
+static gboolean
+is_parent_of (GdkWindow *parent,
+ GdkWindow *child)
+{
+ GdkWindow *w;
+
+ w = child;
+ while (w != NULL)
+ {
+ if (w == parent)
+ return TRUE;
+
+ w = gdk_window_get_parent (w);
+ }
+
+ return FALSE;
+}
+
+static void
+change_impl (GdkWindowObject *private,
+ GdkDrawable *new)
+{
+ GList *l;
+ GdkWindowObject *child;
+ gboolean show;
+ GdkDrawable *old_impl;
+
+ old_impl = private->impl;
+ private->impl = new;
+
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ if (child->impl == old_impl)
+ change_impl (child, new);
+ else
+ {
+ show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
+ (GdkWindow *)private,
+ child->x, child->y);
+ if (show)
+ gdk_window_show_unraised ((GdkWindow *)child);
+ }
+ }
+
+}
+
/**
* gdk_window_reparent:
* @window: a #GdkWindow
gint y)
{
GdkWindowObject *private;
- gboolean show;
-
+ GdkWindowObject *new_parent_private;
+ GdkWindowObject *old_parent;
+ gboolean show, was_toplevel, was_mapped;
+
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
if (GDK_WINDOW_DESTROYED (window) ||
(new_parent && GDK_WINDOW_DESTROYED (new_parent)))
- {
- return;
- }
+ return;
+ if (!new_parent)
+ new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+
private = (GdkWindowObject *) window;
+ new_parent_private = (GdkWindowObject *)new_parent;
+
+ /* No input-output children of input-only windows */
+ if (new_parent_private->input_only && !private->input_only)
+ return;
+
+ /* Don't create loops in hierarchy */
+ if (is_parent_of (window, new_parent))
+ return;
+
+ if (private->cairo_surface)
+ {
+ /* This might be wrong in the new parent, e.g. for non-native surfaces.
+ To make sure we're ok, just wipe it. */
+ cairo_surface_finish (private->cairo_surface);
+ cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+ NULL, NULL);
+ }
+
+ old_parent = private->parent;
/* Break up redirection if inherited */
if (private->redirect && private->redirect->redirected != private)
remove_redirect_from_children (private, private->redirect);
private->redirect = NULL;
}
-
- show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
- /* Inherit parent redirect if we don't have our own */
- if (private->parent && private->redirect == NULL)
+ was_toplevel = private->parent == NULL;
+ was_mapped = GDK_WINDOW_IS_MAPPED (window);
+ show = FALSE;
+
+ if (gdk_window_has_impl (private))
{
- private->redirect = private->parent->redirect;
- apply_redirect_to_children (private, private->redirect);
+ /* Native window */
+ show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
}
+ else
+ {
+ if (new_parent_private->window_type == GDK_WINDOW_ROOT)
+ {
+ /* TODO: We need to convert to a native window here */
+ g_warning ("Reparenting client side windows to the root window not yet supported");
+ return;
+ }
- if (show)
- gdk_window_show (window);
-}
+ show = was_mapped;
+ gdk_window_hide (window);
-static void
-window_remove_filters (GdkWindow *window)
-{
- GdkWindowObject *obj = (GdkWindowObject*) window;
+ change_impl (private, new_parent_private->impl);
+ }
- if (obj->filters)
+ /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
+ * the root window
+ */
+ if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
{
- GList *tmp_list;
-
- for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
- g_free (tmp_list->data);
-
- g_list_free (obj->filters);
- obj->filters = NULL;
+ new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+ new_parent_private = (GdkWindowObject *)new_parent;
}
-}
-/**
- * _gdk_window_destroy_hierarchy:
+ private->parent = new_parent_private;
+ private->x = x;
+ private->y = y;
+
+ if (private->parent)
+ private->parent->children = g_list_remove (private->parent->children, window);
+
+ new_parent_private->children = g_list_prepend (new_parent_private->children, window);
+
+ /* Switch the window type as appropriate */
+
+ switch (GDK_WINDOW_TYPE (new_parent))
+ {
+ case GDK_WINDOW_ROOT:
+ case GDK_WINDOW_FOREIGN:
+ if (private->toplevel_window_type != -1)
+ GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
+ else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+ GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+ break;
+ case GDK_WINDOW_OFFSCREEN:
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_CHILD:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
+ {
+ /* Save the original window type so we can restore it if the
+ * window is reparented back to be a toplevel
+ */
+ private->toplevel_window_type = GDK_WINDOW_TYPE (window);
+ GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
+ }
+ }
+
+ /* Inherit parent redirect if we don't have our own */
+ if (private->parent && private->redirect == NULL)
+ {
+ private->redirect = private->parent->redirect;
+ apply_redirect_to_children (private, private->redirect);
+ }
+
+ recompute_visible_regions (private, TRUE, FALSE);
+ if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
+ recompute_visible_regions (old_parent, FALSE, TRUE);
+
+ if (show)
+ gdk_window_show_unraised (window);
+ else
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+/**
+ * gdk_window_set_has_native:
+ * @window: a #GdkWindow
+ * @has_native: whethe the window should have a native window
+ *
+ * Tries to create or remove a window-system native window for this
+ * GdkWindow. This may fail in some situations. For instance:
+ *
+ * Toplevel and foreign windows must have a native window.
+ * Offscreen window and children of them can never have native windows.
+ * Some backends may not support native child windows.
+ *
+ **/
+void
+gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
+{
+ GdkWindowObject *private;
+ GdkWindowObject *impl_window;
+ GdkDrawable *new_impl, *old_impl;
+ GdkScreen *screen;
+ GdkVisual *visual;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ private = (GdkWindowObject *) window;
+
+ if (has_native)
+ {
+ /* Create native window */
+
+ if (gdk_window_has_impl (private))
+ /* Already has an impl, either native (ok) or
+ offscreen (not supported). Bail. */
+ return;
+
+ impl_window = gdk_window_get_impl_window (private);
+ if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
+ return; /* native in offscreens not supported */
+
+ screen = gdk_drawable_get_screen (window);
+ visual = gdk_drawable_get_visual (window);
+
+ old_impl = private->impl;
+ _gdk_window_impl_new (window, screen, visual, GDK_EXPOSURE_MASK, NULL, 0);
+ new_impl = private->impl;
+
+ private->impl = old_impl;
+ change_impl (private, new_impl);
+ }
+ else
+ {
+ /* Remove native window */
+
+ if (!gdk_window_has_impl (private))
+ return; /* Not native, can't remove */
+
+ if (private->window_type == GDK_WINDOW_OFFSCREEN)
+ return; /* Not native, can't remove */
+
+ if (private->parent == NULL ||
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ return; /* toplevel, must be native */
+
+ /* TODO: remove native */
+ }
+}
+
+static void
+window_remove_filters (GdkWindow *window)
+{
+ GdkWindowObject *obj = (GdkWindowObject*) window;
+
+ if (obj->filters)
+ {
+ GList *tmp_list;
+
+ for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
+ g_free (tmp_list->data);
+
+ g_list_free (obj->filters);
+ obj->filters = NULL;
+ }
+}
+
+/**
+ * _gdk_window_destroy_hierarchy:
* @window: a #GdkWindow
* @recursing: If TRUE, then this is being called because a parent
* was destroyed. This generally means that the call to the
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
case GDK_WINDOW_FOREIGN:
+ case GDK_WINDOW_OFFSCREEN:
if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
{
/* Logically, it probably makes more sense to send
}
else
{
- private->state |= GDK_WINDOW_STATE_WITHDRAWN;
-
if (private->parent)
{
GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
parent_private->children = g_list_remove (parent_private->children, window);
}
- _gdk_window_clear_update_area (window);
gdk_window_free_paint_stack (window);
if (private->bg_pixmap &&
g_list_free (children);
}
+
+ _gdk_window_clear_update_area (window);
- _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+ if (private->cairo_surface)
+ {
+ cairo_surface_finish (private->cairo_surface);
+ cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+ NULL, NULL);
+ }
+
+ if (gdk_window_has_impl (private))
+ {
+ if (gdk_window_is_offscreen (private))
+ _gdk_offscreen_window_destroy (window, recursing);
+ else
+ _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+ }
+ else
+ {
+ /* hide to make sure we repaint and break grabs */
+ gdk_window_hide (window);
+ /* NULL out impl so we don't double free it on finalize */
+ private->impl = NULL;
+ }
+
+ private->state |= GDK_WINDOW_STATE_WITHDRAWN;
private->parent = NULL;
private->destroyed = TRUE;
return private->state;
}
+
+/* This creates an empty "implicit" paint region for the impl window.
+ * By itself this does nothing, but real paints to this window
+ * or children of it can use this pixmap as backing to avoid allocating
+ * multiple pixmaps for subwindow rendering. When doing so they
+ * add to the region of the implicit paint region, which will be
+ * pushed to the window when the implicit paint region is ended.
+ * Such paints should not copy anything to the window on paint end, but
+ * should rely on the implicit paint end.
+ * The implicit paint will be automatically ended if someone draws
+ * directly to the window or a child window.
+ */
+static gboolean
+gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowPaint *paint;
+
+ g_assert (gdk_window_has_impl (private));
+
+ if (GDK_IS_PAINTABLE (private->impl))
+ return FALSE; /* Implementation does double buffering */
+
+ if (private->paint_stack != NULL ||
+ private->implicit_paint != NULL)
+ return FALSE; /* Don't stack implicit paints */
+
+ paint = g_new (GdkWindowPaint, 1);
+ paint->region = gdk_region_new (); /* Empty */
+ paint->x_offset = rect->x;
+ paint->y_offset = rect->y;
+ paint->uses_implicit = FALSE;
+ paint->surface = NULL;
+ paint->pixmap =
+ gdk_pixmap_new (window,
+ MAX (rect->width, 1), MAX (rect->height, 1), -1);
+
+ private->implicit_paint = paint;
+
+ return TRUE;
+}
+
+/* Ensure that all content related to this (sub)window is pushed to the
+ native region */
+static void
+gdk_window_flush_implicit_paint (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
+ GdkWindowPaint *paint;
+ GdkRegion *region;
+ GdkGC *tmp_gc;
+
+ /* Ensure that there is no explicit paint region. */
+ g_assert (private->paint_stack == NULL);
+
+ impl_window = gdk_window_get_impl_window (private);
+ if (impl_window->implicit_paint == NULL)
+ return;
+
+ paint = impl_window->implicit_paint;
+ region = gdk_region_copy (private->clip_region_with_children);
+ gdk_region_offset (region, private->abs_x, private->abs_y);
+ gdk_region_intersect (region, paint->region);
+
+ if (!gdk_region_empty (region))
+ {
+ /* Some regions are valid, push these to window now */
+ tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+ _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
+ gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+ 0, 0, paint->x_offset, paint->y_offset, -1, -1);
+ /* Reset clip region of the cached GdkGC */
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+
+ /* Remove flushed region from the implicit paint */
+ gdk_region_subtract (paint->region, region);
+ }
+ else
+ gdk_region_destroy (region);
+}
+
+/* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
+static void
+gdk_window_end_implicit_paint (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowPaint *paint;
+ GdkGC *tmp_gc;
+
+ g_assert (gdk_window_has_impl (private));
+
+ g_assert (private->implicit_paint != NULL);
+
+ paint = private->implicit_paint;
+
+ private->implicit_paint = NULL;
+
+ if (!gdk_region_empty (paint->region))
+ {
+ /* Some regions are valid, push these to window now */
+ tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+ _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
+ gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+ 0, 0, paint->x_offset, paint->y_offset, -1, -1);
+ /* Reset clip region of the cached GdkGC */
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+ }
+
+ g_object_unref (paint->pixmap);
+ g_free (paint);
+}
+
/**
* gdk_window_begin_paint_rect:
* @window: a #GdkWindow
#ifdef USE_BACKING_STORE
GdkWindowObject *private = (GdkWindowObject *)window;
GdkRectangle clip_box;
- GdkWindowPaint *paint;
+ GdkWindowPaint *paint, *implicit_paint;
+ GdkWindowObject *impl_window;
GSList *list;
g_return_if_fail (GDK_IS_WINDOW (window));
if (iface->begin_paint_region)
iface->begin_paint_region ((GdkPaintable*)private->impl, region);
-
+
return;
}
gdk_region_get_clipbox (region, &clip_box);
+ impl_window = gdk_window_get_impl_window (private);
+ implicit_paint = impl_window->implicit_paint;
+
paint = g_new (GdkWindowPaint, 1);
- paint->region = gdk_region_copy (region);
- paint->x_offset = clip_box.x;
- paint->y_offset = clip_box.y;
- paint->pixmap =
- gdk_pixmap_new (window,
- MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+ if (implicit_paint)
+ {
+ int width, height;
- paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
- cairo_surface_set_device_offset (paint->surface,
- - paint->x_offset, - paint->y_offset);
+ paint->uses_implicit = TRUE;
+ paint->pixmap = g_object_ref (implicit_paint->pixmap);
+ paint->x_offset = -private->abs_x + implicit_paint->x_offset;
+ paint->y_offset = -private->abs_y + implicit_paint->y_offset;
+ paint->region = gdk_region_copy (region);
+ gdk_region_intersect (paint->region, private->clip_region_with_children);
+
+ /* It would be nice if we had some cairo support here so we
+ could set the clip rect on the cairo surface */
+ width = private->abs_x + private->width;
+ height = private->abs_y + private->height;
+
+ paint->surface = _gdk_windowing_create_cairo_surface (((GdkPixmapObject *)paint->pixmap)->impl,
+ width, height);
+ if (paint->surface)
+ cairo_surface_set_device_offset (paint->surface,
+ - paint->x_offset, - paint->y_offset);
+
+ /* Mark the region as valid on the implicit paint */
+ gdk_region_offset (paint->region, private->abs_x, private->abs_y);
+ gdk_region_union (implicit_paint->region, paint->region);
+ gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
+ }
+ else
+ {
+ paint->uses_implicit = FALSE;
+ paint->region = gdk_region_copy (region);
+ paint->x_offset = clip_box.x;
+ paint->y_offset = clip_box.y;
+ paint->pixmap =
+ gdk_pixmap_new (window,
+ MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+
+ paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
+ cairo_surface_set_device_offset (paint->surface,
+ - paint->x_offset, - paint->y_offset);
+ }
+
for (list = private->paint_stack; list != NULL; list = list->next)
{
GdkWindowPaint *tmp_paint = list->data;
private->paint_stack = g_slist_prepend (private->paint_stack, paint);
- if (!gdk_region_empty (region))
+ if (!gdk_region_empty (paint->region))
{
gdk_window_clear_backing_rect (window,
clip_box.x, clip_box.y,
#endif /* USE_BACKING_STORE */
}
+static void
+setup_redirect_clip (GdkWindow *window,
+ GdkGC *gc,
+ int *x_offset_out,
+ int *y_offset_out)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkRegion *visible_region;
+ GdkRectangle dest_rect;
+ GdkRegion *tmpreg;
+ GdkWindow *toplevel;
+ int x_offset, y_offset;
+
+ toplevel = GDK_WINDOW (private->redirect->redirected);
+
+ /* Get the clip region for gc clip rect + window hierarchy in
+ window relative coords */
+ visible_region =
+ _gdk_window_calculate_full_clip_region (window, toplevel,
+ TRUE,
+ &x_offset,
+ &y_offset);
+
+ /* Compensate for the source pos/size */
+ x_offset -= private->redirect->src_x;
+ y_offset -= private->redirect->src_y;
+ dest_rect.x = -x_offset;
+ dest_rect.y = -y_offset;
+ dest_rect.width = private->redirect->width;
+ dest_rect.height = private->redirect->height;
+ tmpreg = gdk_region_rectangle (&dest_rect);
+ gdk_region_intersect (visible_region, tmpreg);
+ gdk_region_destroy (tmpreg);
+
+ /* Compensate for the dest pos */
+ x_offset += private->redirect->dest_x;
+ y_offset += private->redirect->dest_y;
+
+ gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+
+ /* offset clip and tiles from window coords to pixmaps coords */
+ gdk_gc_offset (gc, -x_offset, -y_offset);
+
+ gdk_region_destroy (visible_region);
+
+ *x_offset_out = x_offset;
+ *y_offset_out = y_offset;
+}
+
/**
* gdk_window_end_paint:
* @window: a #GdkWindow
GdkGC *tmp_gc;
GdkRectangle clip_box;
gint x_offset, y_offset;
+ GdkRegion *full_clip;
g_return_if_fail (GDK_IS_WINDOW (window));
}
paint = private->paint_stack->data;
+
private->paint_stack = g_slist_delete_link (private->paint_stack,
- private->paint_stack);
+ private->paint_stack);
gdk_region_get_clipbox (paint->region, &clip_box);
tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, &x_offset, &y_offset);
-
- gdk_gc_set_clip_region (tmp_gc, paint->region);
- gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
-
- gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
- clip_box.x - paint->x_offset,
- clip_box.y - paint->y_offset,
- clip_box.x - x_offset, clip_box.y - y_offset,
- clip_box.width, clip_box.height);
+ x_offset = -private->abs_x;
+ y_offset = -private->abs_y;
+ if (!paint->uses_implicit)
+ {
+ full_clip = gdk_region_copy (private->clip_region_with_children);
+ gdk_region_intersect (full_clip, paint->region);
+ _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
+ gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
+ gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+ clip_box.x - paint->x_offset,
+ clip_box.y - paint->y_offset,
+ clip_box.x - x_offset, clip_box.y - y_offset,
+ clip_box.width, clip_box.height);
+ }
+
if (private->redirect)
{
- GdkWindowClipData data;
-
- setup_redirect_clip (window, tmp_gc, &data);
+ int x_offset, y_offset;
+
+ /* TODO: Should also use paint->region for clipping */
+ setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
clip_box.x - paint->x_offset,
clip_box.y - paint->y_offset,
- clip_box.x + data.x_offset,
- clip_box.y + data.y_offset,
+ clip_box.x + x_offset,
+ clip_box.y + y_offset,
clip_box.width, clip_box.height);
- reset_redirect_clip (window, tmp_gc, &data);
}
/* Reset clip region of the cached GdkGC */
*y_offset = paint->y_offset;
}
else
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, x_offset, y_offset);
+ {
+ *x_offset = -private->abs_x;
+ *y_offset = -private->abs_y;
+ }
}
/**
*y_offset = y_off;
}
+static void
+setup_clip_for_draw (GdkDrawable *drawable,
+ GdkGC *gc,
+ int old_clip_x, int old_clip_y,
+ GdkRegion **old_clip_region)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+ GdkRegion *clip;
+
+ if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
+ clip = gdk_region_copy (private->clip_region_with_children);
+ else
+ clip = gdk_region_copy (private->clip_region);
+
+ /* There was a clip origin set appart from the window offset,
+ need to take this into consideration */
+ if (old_clip_x != 0 || old_clip_y != 0)
+ gdk_region_offset (clip, -old_clip_x, -old_clip_y);
+
+ _gdk_gc_intersect_clip_region (gc, clip, old_clip_region);
+}
+
+static void
+setup_clip_for_paint (GdkDrawable *drawable,
+ GdkWindowPaint *paint,
+ GdkGC *gc,
+ int old_clip_x, int old_clip_y,
+ GdkRegion **old_clip_region)
+{
+ GdkRegion *clip;
+
+ clip = gdk_region_copy (paint->region);
+
+ /* There was a clip origin set appart from the window offset,
+ need to take this into consideration */
+ if (old_clip_x != 0 || old_clip_y != 0)
+ gdk_region_offset (clip, -old_clip_x, -old_clip_y);
+
+ _gdk_gc_intersect_clip_region (gc, clip, old_clip_region);
+}
+
+
#define OFFSET_GC(gc) \
gint x_offset, y_offset; \
gint old_clip_x = gc->clip_x_origin; \
gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
}
+#define SETUP_PAINT_GC_CLIP(gc) \
+ GdkRegion *old_clip_region; \
+ if (paint->uses_implicit) \
+ setup_clip_for_paint (drawable, paint, gc, old_clip_x, \
+ old_clip_y, &old_clip_region);
+
+#define RESTORE_PAINT_GC_CLIP(gc) \
+ if (paint->uses_implicit) \
+ _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+
+
+#define SETUP_DIRECT_GC_CLIP(gc) \
+ GdkRegion *old_clip_region; \
+ gdk_window_flush_implicit_paint ((GdkWindow *)drawable);\
+ setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y, &old_clip_region);
+
+#define RESTORE_DIRECT_GC_CLIP(gc) \
+ _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+
static GdkGC *
gdk_window_create_gc (GdkDrawable *drawable,
GdkGCValues *values,
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_rectangle (paint->pixmap, gc, filled,
x - x_offset, y - y_offset, width, height);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_rectangle (private->impl, gc, filled,
- x - x_offset, y - y_offset, width, height);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_rectangle (private->impl, gc, filled,
+ x - x_offset, y - y_offset, width, height);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_arc (paint->pixmap, gc, filled,
x - x_offset, y - y_offset,
width, height, angle1, angle2);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_arc (private->impl, gc, filled,
- x - x_offset, y - y_offset,
- width, height, angle1, angle2);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_arc (private->impl, gc, filled,
+ x - x_offset, y - y_offset,
+ width, height, angle1, angle2);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
-
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
if (new_points != points)
g_free (new_points);
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_text (paint->pixmap, font, gc,
x - x_offset, y - y_offset, text, text_length);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_text (private->impl, font, gc,
- x - x_offset, y - y_offset, text, text_length);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_text (private->impl, font, gc,
+ x - x_offset, y - y_offset, text, text_length);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_text_wc (paint->pixmap, font, gc,
x - x_offset, y - y_offset, text, text_length);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_text_wc (private->impl, font, gc,
- x - x_offset, y - y_offset, text, text_length);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_text_wc (private->impl, font, gc,
+ x - x_offset, y - y_offset, text, text_length);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
-static GdkDrawable*
+static GdkDrawable *
+gdk_window_get_source_drawable (GdkDrawable *drawable)
+{
+ GdkWindow *window = GDK_WINDOW (drawable);
+ GdkWindowObject *private;
+
+ private = (GdkWindowObject *) window;
+ if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
+ return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
+
+ return drawable;
+}
+
+static GdkDrawable *
gdk_window_get_composite_drawable (GdkDrawable *drawable,
gint x,
gint y,
GdkRectangle rect;
GdkGC *tmp_gc;
gboolean overlap_buffer;
+ GdkDrawable *source;
+ GdkWindowObject *impl_window;
+ GdkWindowPaint *implicit_paint;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (GDK_WINDOW (drawable),
- composite_x_offset,
- composite_y_offset);
-
- if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
- || private->paint_stack == NULL)
- {
- /* No backing store */
- return g_object_ref (drawable);
- }
+ *composite_x_offset = -private->abs_x;
+ *composite_y_offset = -private->abs_y;
- /* See if the buffered part is overlapping the part we want
+ if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
+ return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+
+ /* See if any buffered part is overlapping the part we want
* to get
*/
rect.x = x;
rect.height = height;
overlap_buffer = FALSE;
-
+
for (list = private->paint_stack; list != NULL; list = list->next)
{
GdkWindowPaint *paint = list->data;
GdkOverlapType overlap;
-
+
overlap = gdk_region_rect_in (paint->region, &rect);
-
+
if (overlap == GDK_OVERLAP_RECTANGLE_IN)
{
*composite_x_offset = paint->x_offset;
}
}
- if (!overlap_buffer)
- return g_object_ref (drawable);
+ impl_window = gdk_window_get_impl_window (private);
+ implicit_paint = impl_window->implicit_paint;
+ if (implicit_paint)
+ {
+ GdkOverlapType overlap;
+
+ rect.x += private->abs_x;
+ rect.y += private->abs_y;
+
+ overlap = gdk_region_rect_in (implicit_paint->region, &rect);
+ if (overlap == GDK_OVERLAP_RECTANGLE_IN)
+ {
+ *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
+ *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
+
+ return g_object_ref (implicit_paint->pixmap);
+ }
+ else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+ overlap_buffer = TRUE;
+ }
+ if (!overlap_buffer)
+ return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+
tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
+ source = _gdk_drawable_get_source_drawable (drawable);
+
/* Copy the current window contents */
gdk_draw_drawable (tmp_pixmap,
tmp_gc,
- private->impl,
+ GDK_WINDOW_OBJECT (source)->impl,
x - *composite_x_offset,
y - *composite_y_offset,
0, 0,
width, height);
/* paint the backing stores */
+ if (implicit_paint)
+ {
+ GdkWindowPaint *paint = list->data;
+
+ gdk_gc_set_clip_region (tmp_gc, paint->region);
+ gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
+
+ gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
+ x - paint->x_offset,
+ y - paint->y_offset,
+ 0, 0, width, height);
+ }
+
for (list = private->paint_stack; list != NULL; list = list->next)
{
GdkWindowPaint *paint = list->data;
+ if (paint->uses_implicit)
+ continue; /* We already copied this above */
+
gdk_gc_set_clip_region (tmp_gc, paint->region);
gdk_gc_set_clip_origin (tmp_gc, -x, -y);
y - paint->y_offset,
0, 0, width, height);
}
-
+
/* Reset clip region of the cached GdkGC */
gdk_gc_set_clip_region (tmp_gc, NULL);
GdkWindowObject *private = (GdkWindowObject *)drawable;
GdkRegion *result;
- result = gdk_drawable_get_clip_region (private->impl);
+ result = gdk_region_copy (private->clip_region);
if (private->paint_stack)
{
gdk_window_get_visible_region (GdkDrawable *drawable)
{
GdkWindowObject *private = (GdkWindowObject*) drawable;
-
- return gdk_drawable_get_visible_region (private->impl);
+
+ return gdk_region_copy (private->clip_region);
}
static void
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_drawable (paint->pixmap, gc,
src, xsrc, ysrc,
xdest - x_offset, ydest - y_offset, width, height);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_drawable (private->impl, gc,
- src, xsrc, ysrc,
- xdest - x_offset, ydest - y_offset,
- width, height);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_drawable (private->impl, gc,
+ src, xsrc, ysrc,
+ xdest - x_offset, ydest - y_offset,
+ width, height);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_points (paint->pixmap, gc, new_points, npoints);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_points (private->impl, gc, points, npoints);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_points (private->impl, gc, points, npoints);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
if (new_points != points)
g_free (new_points);
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
if (new_segs != segs)
g_free (new_segs);
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_lines (private->impl, gc, new_points, npoints);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_lines (private->impl, gc, new_points, npoints);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
if (new_points != points)
g_free (new_points);
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_glyphs (private->impl, gc, font,
- x - x_offset, y - y_offset, glyphs);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_glyphs (private->impl, gc, font,
+ x - x_offset, y - y_offset, glyphs);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (GDK_WINDOW_DESTROYED (window))
return;
+ clip_region = _gdk_window_calculate_full_clip_region (window,
+ GDK_WINDOW (redirect->redirected),
+ TRUE,
+ &x_offset, &y_offset);
+
paint.x_offset = x_offset;
paint.y_offset = y_offset;
paint.pixmap = redirect->pixmap;
paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
- clip_region = _gdk_window_calculate_full_clip_region (window,
- GDK_WINDOW (redirect->redirected),
- NULL, TRUE,
- &x_offset, &y_offset);
-
method.cr = NULL;
method.gc = NULL;
setup_backing_rect_method (&method, window, &paint, 0, 0);
cairo_surface_destroy (paint.surface);
}
+static void
+gdk_window_clear_backing_rect_direct (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ BackingRectMethod method;
+ GdkWindowPaint paint;
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ paint.x_offset = 0;
+ paint.y_offset = 0;
+ paint.pixmap = window;
+ paint.surface = _gdk_drawable_ref_cairo_surface (window);
+
+ method.cr = NULL;
+ method.gc = NULL;
+ setup_backing_rect_method (&method, window, &paint, 0, 0);
+
+ if (method.cr)
+ {
+ g_assert (method.gc == NULL);
+
+ gdk_cairo_region (method.cr, private->clip_region_with_children);
+ cairo_clip (method.cr);
+
+ cairo_rectangle (method.cr, x, y, width, height);
+ cairo_fill (method.cr);
+
+ cairo_destroy (method.cr);
+ }
+ else
+ {
+ g_assert (method.gc != NULL);
+
+ gdk_gc_set_clip_region (method.gc, private->clip_region_with_children);
+ gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
+ g_object_unref (method.gc);
+
+ }
+
+ cairo_surface_destroy (paint.surface);
+}
+
/**
* gdk_window_clear:
width, height);
}
+static void
+gdk_window_clear_area_internal (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gboolean send_expose)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (private->paint_stack)
+ gdk_window_clear_backing_rect (window, x, y, width, height);
+ else
+ {
+ if (private->redirect)
+ gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
+
+
+
+ gdk_window_clear_backing_rect_direct (window, x, y, width, height);
+ if (send_expose)
+ {
+ GdkRectangle rect;
+
+ rect.x = x;
+ rect.y = x;
+ rect.width = width;
+ rect.height = height;
+
+ gdk_window_invalidate_rect (window, &rect, FALSE);
+ }
+ }
+}
+
+
/**
* gdk_window_clear_area:
* @window: a #GdkWindow
gint width,
gint height)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (private->paint_stack)
- gdk_window_clear_backing_rect (window, x, y, width, height);
- else
- {
- if (private->redirect)
- gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
- x, y,
- width, height,
- FALSE);
- }
+ gdk_window_clear_area_internal (window,
+ x, y,
+ width, height,
+ FALSE);
}
/**
gint width,
gint height)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (private->paint_stack)
- gdk_window_clear_backing_rect (window, x, y, width, height);
-
- if (private->redirect)
- gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
- x, y,
- width, height,
- TRUE);
+ gdk_window_clear_area_internal (window,
+ x, y,
+ width, height,
+ TRUE);
}
static void
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
xdest - x_offset, ydest - y_offset,
width, height);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
- xdest - x_offset, ydest - y_offset,
- width, height);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
+ xdest - x_offset, ydest - y_offset,
+ width, height);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
dest_x - x_offset, dest_y - y_offset,
width, height,
dither, x_dither - x_offset, y_dither - y_offset);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
- dest_x - x_offset, dest_y - y_offset,
- width, height,
- dither, x_dither, y_dither);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
+ dest_x - x_offset, dest_y - y_offset,
+ width, height,
+ dither, x_dither, y_dither);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ /* TODO: Do paint clipping here... */
gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
dest_x - x_offset, dest_y - y_offset,
width, height,
dither, x_dither - x_offset, y_dither - y_offset);
}
else
- gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
- dest_x - x_offset, dest_y - y_offset,
- width, height,
- dither, x_dither, y_dither);
+ {
+ /* TODO: No GC passed in, but still want clipping here... */
+ gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
+ dest_x - x_offset, dest_y - y_offset,
+ width, height,
+ dither, x_dither, y_dither);
+ }
}
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
+ SETUP_PAINT_GC_CLIP (gc);
gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
g_free (new_trapezoids);
gint *width,
gint *height)
{
- g_return_if_fail (GDK_IS_WINDOW (drawable));
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
- gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
- width, height);
+ if (width)
+ *width = private->width;
+ if (height)
+ *height = private->height;
}
static GdkVisual*
/* If we're here, a composite image was not necessary, so
* we can ignore the paint stack.
*/
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (drawable,
- &x_offset, &y_offset);
+
+ /* TODO: Is this right? */
+ x_offset = 0;
+ y_offset = 0;
return gdk_drawable_copy_to_image (private->impl,
image,
width, height);
}
+static void
+gdk_window_cairo_surface_destroy (void *data)
+{
+ GdkWindowObject *private = (GdkWindowObject*) data;
+
+ private->cairo_surface = NULL;
+}
+
static cairo_surface_t *
gdk_window_ref_cairo_surface (GdkDrawable *drawable)
{
cairo_surface_reference (surface);
}
else
- surface = _gdk_drawable_ref_cairo_surface (private->impl);
+ {
+
+ /* This will be drawing directly to the window, so flush implicit paint */
+ gdk_window_flush_implicit_paint ((GdkWindow *)drawable);
+
+ if (!private->cairo_surface)
+ {
+ int width, height;
+ GdkDrawable *source;
+
+ /* It would be nice if we had some cairo support here so we
+ could set the clip rect on the cairo surface */
+ width = private->abs_x + private->width;
+ height = private->abs_y + private->height;
+
+ source = _gdk_drawable_get_source_drawable (drawable);
+
+ /* TODO: Avoid the typecheck crap by adding virtual call */
+ private->cairo_surface = _gdk_windowing_create_cairo_surface (GDK_IS_PIXMAP (source) ? GDK_PIXMAP_OBJECT(source)->impl : GDK_WINDOW_OBJECT(source)->impl,
+ width, height);
+
+ if (private->cairo_surface)
+ {
+ cairo_surface_set_device_offset (private->cairo_surface,
+ private->abs_x,
+ private->abs_y);
+
+ cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+ drawable, gdk_window_cairo_surface_destroy);
+ }
+ }
+ else
+ cairo_surface_reference (private->cairo_surface);
+
+ surface = private->cairo_surface;
+ }
return surface;
}
+static void
+gdk_window_set_cairo_clip (GdkDrawable *drawable,
+ cairo_t *cr)
+{
+ GdkWindowObject *private = (GdkWindowObject*) drawable;
+
+ if (!private->paint_stack)
+ {
+ cairo_save (cr);
+ cairo_identity_matrix (cr);
+
+ cairo_new_path (cr);
+ gdk_cairo_region (cr, private->clip_region);
+
+ cairo_restore (cr);
+ cairo_clip (cr);
+ }
+ else
+ {
+ GdkWindowPaint *paint = private->paint_stack->data;
+
+ /* Only needs to clip to region if piggybacking
+ on an implicit paint pixmap */
+ if (paint->uses_implicit)
+ {
+ cairo_save (cr);
+ cairo_identity_matrix (cr);
+
+ cairo_new_path (cr);
+ gdk_cairo_region (cr, paint->region);
+ cairo_restore (cr);
+
+ cairo_clip (cr);
+ }
+ }
+}
+
/* Code for dirty-region queueing
*/
static GSList *update_windows = NULL;
static guint update_idle = 0;
static gboolean debug_updates = FALSE;
+static inline gboolean
+gdk_window_is_ancestor (GdkWindow *window,
+ GdkWindow *ancestor)
+{
+ while (window)
+ {
+ GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
+
+ if (parent == ancestor)
+ return TRUE;
+
+ window = parent;
+ }
+
+ return FALSE;
+}
+
+static void
+gdk_window_add_update_window (GdkWindow *window)
+{
+ GSList *tmp;
+ GSList *prev = NULL;
+ gboolean has_ancestor_in_list = FALSE;
+
+ for (tmp = update_windows; tmp; tmp = tmp->next)
+ {
+ GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
+
+ /* check if tmp is an ancestor of "window"; if it is, set a
+ * flag indicating that all following windows are either
+ * children of "window" or from a differen hierarchy
+ */
+ if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
+ has_ancestor_in_list = TRUE;
+
+ /* insert in reverse stacking order when adding around siblings,
+ * so processing updates properly paints over lower stacked windows
+ */
+ if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
+ {
+ gint index = g_list_index (parent->children, window);
+ for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
+ {
+ gint sibling_index = g_list_index (parent->children, tmp->data);
+ if (index > sibling_index)
+ break;
+ prev = tmp;
+ }
+ /* here, tmp got advanced past all lower stacked siblings */
+ tmp = g_slist_prepend (tmp, window);
+ if (prev)
+ prev->next = tmp;
+ else
+ update_windows = tmp;
+ return;
+ }
+
+ /* if "window" has an ancestor in the list and tmp is one of
+ * "window's" children, insert "window" before tmp
+ */
+ if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
+ {
+ tmp = g_slist_prepend (tmp, window);
+
+ if (prev)
+ prev->next = tmp;
+ else
+ update_windows = tmp;
+ return;
+ }
+
+ /* if we're at the end of the list and had an ancestor it it,
+ * append to the list
+ */
+ if (! tmp->next && has_ancestor_in_list)
+ {
+ tmp = g_slist_append (tmp, window);
+ return;
+ }
+
+ prev = tmp;
+ }
+
+ /* if all above checks failed ("window" is from a different
+ * hierarchy than what is already in the list) or the list is
+ * empty, prepend
+ */
+ update_windows = g_slist_prepend (update_windows, window);
+}
+
+static void
+gdk_window_remove_update_window (GdkWindow *window)
+{
+ update_windows = g_slist_remove (update_windows, window);
+}
+
static gboolean
gdk_window_update_idle (gpointer data)
{
}
}
+static void
+gdk_window_process_updates_recurse (GdkWindow *window,
+ GdkRegion *expose_region)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *child;
+ GdkRegion *child_region;
+ GdkRectangle r;
+ GList *l;
+
+ if (gdk_region_empty (expose_region))
+ return;
+
+ /* Iterate over children, starting at topmost */
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
+ continue;
+
+ /* Ignore offscreen children, as they don't draw in their parent and
+ * don't take part in the clipping */
+ if (gdk_window_is_offscreen (child))
+ continue;
+
+ r.x = child->x;
+ r.y = child->y;
+ r.width = child->width;
+ r.height = child->height;
+
+ child_region = gdk_region_rectangle (&r);
+
+ if (child->impl == private->impl)
+ {
+ /* Client side child, expose */
+ gdk_region_intersect (child_region, expose_region);
+ gdk_region_subtract (expose_region, child_region);
+ gdk_region_offset (child_region, -child->x, -child->y);
+ gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
+ }
+ else
+ {
+ /* Native child, just remove area from expose region */
+ gdk_region_subtract (expose_region, child_region);
+ }
+ gdk_region_destroy (child_region);
+ }
+
+ if (private->event_mask & GDK_EXPOSURE_MASK)
+ {
+ GdkEvent event;
+
+ event.expose.type = GDK_EXPOSE;
+ event.expose.window = g_object_ref (window);
+ event.expose.send_event = FALSE;
+ event.expose.count = 0;
+ event.expose.region = expose_region;
+ gdk_region_get_clipbox (expose_region, &event.expose.area);
+
+ (*_gdk_event_func) (&event, _gdk_event_data);
+
+ g_object_unref (window);
+ }
+}
+
static void
gdk_window_process_updates_internal (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
gboolean save_region = FALSE;
+ GdkRectangle clip_box;
/* If an update got queued during update processing, we can get a
* window in the update queue that has an empty update_area.
GdkRectangle window_rect;
GdkRegion *expose_region;
GdkRegion *window_region;
- gint width, height;
+ gboolean end_implicit;
if (debug_updates)
{
gdk_display_sync (gdk_drawable_get_display (window));
g_usleep (70000);
}
-
- save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
+ save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
if (save_region)
expose_region = gdk_region_copy (update_area);
else
expose_region = update_area;
- gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
-
window_rect.x = 0;
window_rect.y = 0;
- window_rect.width = width;
- window_rect.height = height;
+ window_rect.width = private->width;
+ window_rect.height = private->height;
window_region = gdk_region_rectangle (&window_rect);
gdk_region_intersect (expose_region,
window_region);
gdk_region_destroy (window_region);
-
- if (!gdk_region_empty (expose_region) &&
- (private->event_mask & GDK_EXPOSURE_MASK))
- {
- GdkEvent event;
-
- event.expose.type = GDK_EXPOSE;
- event.expose.window = g_object_ref (window);
- event.expose.send_event = FALSE;
- event.expose.count = 0;
- event.expose.region = expose_region;
- gdk_region_get_clipbox (expose_region, &event.expose.area);
-
- (*_gdk_event_func) (&event, _gdk_event_data);
-
- g_object_unref (window);
- }
+ gdk_region_get_clipbox (expose_region, &clip_box);
+ end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
+ gdk_window_process_updates_recurse (window, expose_region);
+ if (end_implicit)
+ gdk_window_end_implicit_paint (window);
+
if (expose_region != update_area)
gdk_region_destroy (expose_region);
}
{
if (private->update_freeze_count ||
gdk_window_is_toplevel_frozen (tmp_list->data))
- update_windows = g_slist_prepend (update_windows, private);
+ gdk_window_add_update_window ((GdkWindow *) private);
else
gdk_window_process_updates_internal (tmp_list->data);
}
gboolean update_children)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
g_return_if_fail (GDK_IS_WINDOW (window));
return;
}
-
- if (private->update_area &&
- !private->update_freeze_count &&
+
+ impl_window = gdk_window_get_impl_window (private);
+ if (impl_window->update_area &&
+ !impl_window->update_freeze_count &&
!gdk_window_is_toplevel_frozen (window))
{
- gdk_window_process_updates_internal (window);
- update_windows = g_slist_remove (update_windows, window);
+ gdk_window_process_updates_internal ((GdkWindow *)impl_window);
+ gdk_window_remove_update_window ((GdkWindow *)impl_window);
}
if (update_children)
{
- GList *tmp_list = private->children;
- while (tmp_list)
- {
- gdk_window_process_updates (tmp_list->data, TRUE);
- tmp_list = tmp_list->next;
- }
+ /* process updates in reverse stacking order so composition or
+ * painting over achieves the desired effect for offscreen windows
+ */
+ GList *node;
+ for (node = g_list_last (private->children); node; node = node->prev)
+ gdk_window_process_updates (node->data, TRUE);
}
}
gpointer user_data)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
GdkRegion *visible_region;
GList *tmp_list;
return;
}
- /* windows that a redirection has ben setup for need to be considered
- * fully visible, in order to avoid missing redirected paint ops
- * anywhere in the window area.
- */
- if (private->redirect && private->redirect->redirected == private)
- {
- GdkRectangle visible_rect = { 0, 0, 0, 0 };
- gdk_drawable_get_size (GDK_DRAWABLE (window), &visible_rect.width, &visible_rect.height);
- visible_region = gdk_region_rectangle (&visible_rect);
- }
- else
- visible_region = gdk_drawable_get_visible_region (window);
+ visible_region = gdk_drawable_get_visible_region (window);
gdk_region_intersect (visible_region, region);
tmp_list = private->children;
{
GdkRegion *child_region;
GdkRectangle child_rect;
-
- gdk_window_get_position ((GdkWindow *)child,
- &child_rect.x, &child_rect.y);
- gdk_drawable_get_size ((GdkDrawable *)child,
- &child_rect.width, &child_rect.height);
+ child_rect.x = child->x;
+ child_rect.y = child->y;
+ child_rect.width = child->width;
+ child_rect.height = child->height;
child_region = gdk_region_rectangle (&child_rect);
/* remove child area from the invalid area of the parent */
if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
- !child->composited)
+ !child->composited &&
+ !gdk_window_is_offscreen (child))
gdk_region_subtract (visible_region, child_region);
if (child_func && (*child_func) ((GdkWindow *)child, user_data))
{
if (debug_updates)
draw_ugly_color (window, region);
-
- if (private->update_area)
+
+ /* Convert to impl coords */
+ impl_window = gdk_window_get_impl_window (private);
+ gdk_region_offset (visible_region, private->abs_x, private->abs_y);
+ if (impl_window->update_area)
{
- gdk_region_union (private->update_area, visible_region);
+ gdk_region_union (impl_window->update_area, visible_region);
}
else
{
- update_windows = g_slist_prepend (update_windows, window);
- private->update_area = gdk_region_copy (visible_region);
+ gdk_window_add_update_window ((GdkWindow *)impl_window);
+ impl_window->update_area = gdk_region_copy (visible_region);
- gdk_window_schedule_update (window);
+ gdk_window_schedule_update ((GdkWindow *)impl_window);
}
}
NULL);
}
+/**
+ * _gdk_window_invalidate_for_expose:
+ * @window: a #GdkWindow
+ * @region: a #GdkRegion
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or "dirty region." The call
+ * gdk_window_process_updates() sends one or more expose events to the
+ * window, which together cover the entire update area. An
+ * application would normally redraw the contents of @window in
+ * response to those expose events.
+ *
+ * GDK will call gdk_window_process_all_updates() on your behalf
+ * whenever your program returns to the main loop and becomes idle, so
+ * normally there's no need to do that manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * This version of invalidation is used when you recieve expose events
+ * from the native window system. It exposes the native window, plus
+ * any non-native child windows (but not native child windows, as those would
+ * have gotten their own expose events).
+ **/
+void
+_gdk_window_invalidate_for_expose (GdkWindow *window,
+ const GdkRegion *region)
+{
+ gdk_window_invalidate_maybe_recurse (window, region,
+ (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
+ NULL);
+}
+
+
/**
* gdk_window_get_update_area:
* @window: a #GdkWindow
gdk_window_get_update_area (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
GdkRegion *tmp_region;
g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
- if (private->update_area)
+ impl_window = gdk_window_get_impl_window (private);
+
+ if (impl_window->update_area)
{
- tmp_region = private->update_area;
- private->update_area = NULL;
+ tmp_region = gdk_region_copy (private->clip_region_with_children);
+ /* Convert to impl coords */
+ gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
+ gdk_region_intersect (tmp_region, impl_window->update_area);
- update_windows = g_slist_remove (update_windows, window);
-
- return tmp_region;
+ if (gdk_region_empty (tmp_region))
+ {
+ gdk_region_destroy (tmp_region);
+ return NULL;
+ }
+ else
+ {
+ gdk_region_subtract (impl_window->update_area, tmp_region);
+
+ if (gdk_region_empty (impl_window->update_area))
+ {
+ gdk_region_destroy (impl_window->update_area);
+ impl_window->update_area = NULL;
+
+ gdk_window_remove_update_window ((GdkWindow *)impl_window);
+ }
+
+ /* Convert from impl coords */
+ gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
+ return tmp_region;
+
+ }
}
else
return NULL;
if (private->update_area)
{
- update_windows = g_slist_remove (update_windows, window);
-
+ gdk_window_remove_update_window (window);
+
gdk_region_destroy (private->update_area);
private->update_area = NULL;
}
gdk_window_freeze_updates (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
g_return_if_fail (GDK_IS_WINDOW (window));
- private->update_freeze_count++;
+ impl_window = gdk_window_get_impl_window (private);
+ impl_window->update_freeze_count++;
}
/**
gdk_window_thaw_updates (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (private->update_freeze_count > 0);
- if (--private->update_freeze_count == 0)
- gdk_window_schedule_update (window);
+ impl_window = gdk_window_get_impl_window (private);
+
+ if (--impl_window->update_freeze_count == 0)
+ gdk_window_schedule_update (GDK_WINDOW (impl_window));
}
/**
return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
}
+/* Called when window becomes viewable. Clears and sends exposes
+ for all the already mapped windows in the hierarchy */
+static void
+synthesize_clears (GdkWindowObject *window)
+{
+ GList *l;
+
+ if (!gdk_window_has_impl (window) && !window->input_only)
+ {
+ gdk_window_clear_area_e (GDK_WINDOW (window),
+ 0, 0,
+ window->width, window->height);
+ }
+
+ for (l = window->children; l != NULL; l = l->next)
+ {
+ GdkWindow *child = GDK_WINDOW (l->data);
+
+ if (GDK_WINDOW_IS_MAPPED (child))
+ synthesize_clears (GDK_WINDOW_OBJECT (child));
+ }
+}
+
+static inline void
+gdk_window_raise_internal (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *parent = private->parent;
+
+ if (parent)
+ {
+ parent->children = g_list_remove (parent->children, window);
+ parent->children = g_list_prepend (parent->children, window);
+ }
+}
+
+static void
+gdk_window_show_internal (GdkWindow *window, gboolean raise)
+{
+ GdkWindowObject *private;
+ gboolean was_mapped;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return;
+
+ was_mapped = GDK_WINDOW_IS_MAPPED (window);
+
+ if (raise)
+ {
+ /* Keep children in (reverse) stacking order */
+ gdk_window_raise_internal (window);
+ }
+
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, raise);
+ else
+ {
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ /* If we're raising, need to invalidate even if we're already shown */
+ if (raise && gdk_window_is_viewable (window) && !private->input_only)
+ gdk_window_invalidate_rect (window, NULL, TRUE);
+ }
+ else
+ {
+ /* Wasn't visible already */
+ private->state = 0;
+ }
+ }
+
+ if (!was_mapped)
+ {
+ if (private->event_mask & GDK_STRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+
+ if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+ }
+
+ if (!was_mapped || raise)
+ {
+ if (gdk_window_is_viewable (window))
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+
+ recompute_visible_regions (private, TRUE, FALSE);
+ }
+
+ if (!was_mapped && gdk_window_is_viewable (window))
+ synthesize_clears (private);
+
+}
+
/**
* gdk_window_show_unraised:
* @window: a #GdkWindow
void
gdk_window_show_unraised (GdkWindow *window)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
-}
-
-static inline void
-gdk_window_raise_internal (GdkWindow *window)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowObject *parent = private->parent;
-
- if (parent)
- {
- parent->children = g_list_remove (parent->children, window);
- parent->children = g_list_prepend (parent->children, window);
- }
+ gdk_window_show_internal (window, FALSE);
}
/**
gdk_window_raise_internal (window);
GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+
+ recompute_visible_regions (private, TRUE, FALSE);
}
static void
}
}
+static void
+gdk_window_invalidate_in_parent (GdkWindowObject *private)
+{
+ GdkRectangle r, child;
+
+ if (private->parent == NULL ||
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ return;
+
+ /* get the visible rectangle of the parent */
+ r.x = r.y = 0;
+ r.width = private->parent->width;
+ r.height = private->parent->height;
+
+ child.x = private->x;
+ child.y = private->y;
+ child.width = private->width;
+ child.height = private->height;
+ gdk_rectangle_intersect (&r, &child, &r);
+
+ gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
+}
+
+
/**
* gdk_window_lower:
* @window: a #GdkWindow
/* Keep children in (reverse) stacking order */
gdk_window_lower_internal (window);
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+ else
+ {
+ gdk_window_invalidate_in_parent (private);
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+ }
+
+ recompute_visible_regions (private, TRUE, FALSE);
}
/**
void
gdk_window_show (GdkWindow *window)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
-
- /* Keep children in (reverse) stacking order */
- gdk_window_raise_internal (window);
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, TRUE);
+ gdk_window_show_internal (window, TRUE);
}
/**
gdk_window_hide (GdkWindow *window)
{
GdkWindowObject *private;
+ gboolean was_mapped;
g_return_if_fail (GDK_IS_WINDOW (window));
if (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+ was_mapped = GDK_WINDOW_IS_MAPPED (private);
+
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+ else if (was_mapped)
+ {
+ GdkDisplay *display;
+
+ /* May need to break grabs on children */
+ display = gdk_drawable_get_display (window);
+
+ if (display->pointer_grab.window != NULL)
+ {
+ if (is_parent_of (window, display->pointer_grab.window))
+ {
+ /* Call this ourselves, even though gdk_display_pointer_ungrab
+ does so too, since we want to pass implicit == TRUE so the
+ broken grab event is generated */
+ _gdk_display_unset_has_pointer_grab (display,
+ TRUE,
+ FALSE,
+ GDK_CURRENT_TIME);
+ gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+ }
+ }
+
+ private->state = GDK_WINDOW_STATE_WITHDRAWN;
+
+ /* Invalidate the rect */
+ gdk_window_invalidate_in_parent (private);
+ }
+
+ if (was_mapped)
+ {
+ if (private->event_mask & GDK_STRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+ if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+ _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+ }
+
+ recompute_visible_regions (private, TRUE, FALSE);
}
/**
gdk_window_withdraw (GdkWindow *window)
{
GdkWindowObject *private;
+ gboolean was_mapped;
g_return_if_fail (GDK_IS_WINDOW (window));
if (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+ was_mapped = GDK_WINDOW_IS_MAPPED (private);
+
+ if (gdk_window_has_impl (private))
+ {
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+
+ if (was_mapped)
+ {
+ if (private->event_mask & GDK_STRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+ if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+ _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+ }
+
+ recompute_visible_regions (private, TRUE, FALSE);
+ }
}
/**
if (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, event_mask);
+ private->event_mask = event_mask;
}
/**
if (private->destroyed)
return 0;
- return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_events (window);
+ return private->event_mask;
+}
+
+static void
+move_native_children (GdkWindowObject *private)
+{
+ GList *l;
+ GdkWindowObject *child;
+
+ for (l = private->children; l; l = l->next)
+ {
+ child = l->data;
+
+ if (child->impl != private->impl)
+ GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
+ else
+ move_native_children (child);
+ }
+}
+
+
+static void
+gdk_window_move_resize_internal (GdkWindow *window,
+ gboolean with_move,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowObject *private;
+ GdkRegion *old_region, *new_region, *copy_area;
+ GdkWindowObject *impl_window;
+ gboolean expose;
+ int old_x, old_y, old_abs_x, old_abs_y;
+ int dx, dy;
+ GdkRectangle copy_rect;
+ GdkGC *tmp_gc;
+ gboolean do_move_native_children;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return;
+
+ do_move_native_children = FALSE;
+ expose = FALSE;
+ old_region = NULL;
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ old_x = private->x;
+ old_y = private->y;
+
+ if (gdk_window_has_impl (private))
+ {
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ expose = TRUE;
+ old_region = gdk_region_copy (private->clip_region);
+ /* Adjust region to parent window coords */
+ gdk_region_offset (old_region, private->x, private->y);
+ }
+
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
+ }
+ else
+ {
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ expose = TRUE;
+ old_region = gdk_region_copy (private->clip_region);
+ /* Adjust region to parent window coords */
+ gdk_region_offset (old_region, private->x, private->y);
+ }
+
+ if (with_move)
+ {
+ private->x = x;
+ private->y = y;
+ }
+ if (!(width < 0 && height < 0))
+ {
+ if (width < 1)
+ width = 1;
+ private->width = width;
+ if (height < 1)
+ height = 1;
+ private->height = height;
+ }
+
+ do_move_native_children = TRUE;
+ }
+
+ dx = private->x - old_x;
+ dy = private->y - old_y;
+
+ old_abs_x = private->abs_x;
+ old_abs_y = private->abs_y;
+
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ if (do_move_native_children &&
+ (old_abs_x != private->abs_x ||
+ old_abs_y != private->abs_y))
+ move_native_children (private);
+
+ if (expose)
+ {
+ new_region = gdk_region_copy (private->clip_region);
+ /* Adjust region to parent window coords */
+ gdk_region_offset (new_region, private->x, private->y);
+
+ /* copy_area:
+ * Part of the data at the new location can be copied from the
+ * old location, this area is the intersection of the old region
+ * moved as the copy will move it and then intersected with
+ * the new region.
+ *
+ * new_region:
+ * Everything in the old and new regions that is not copied must be
+ * invalidated (including children) as this is newly exposed
+ */
+ copy_area = gdk_region_copy (new_region);
+
+ gdk_region_union (new_region, old_region);
+
+ gdk_region_offset (old_region, dx, dy);
+ gdk_region_intersect (copy_area, old_region);
+
+ gdk_region_subtract (new_region, copy_area);
+
+ /* Convert old region to impl coords */
+ gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
+
+ /* The old_region area is moved and we queue translations for all expose events
+ to it that will be sent before the copy operation */
+ /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
+ if (!gdk_window_is_offscreen (impl_window))
+ _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, old_region, dx, dy);
+
+ /* convert from parent coords to real parent */
+ gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
+ gdk_region_get_clipbox (copy_area, ©_rect);
+ tmp_gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+ gdk_gc_set_clip_region (tmp_gc, copy_area);
+ gdk_draw_drawable (private->impl,
+ tmp_gc,
+ private->impl,
+ copy_rect.x-dx, copy_rect.y-dy,
+ copy_rect.x, copy_rect.y,
+ copy_rect.width, copy_rect.height);
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+
+ /* Move any old invalid regions in the copy source area by dx/dy */
+ if (impl_window->update_area)
+ {
+ /* Convert from target to source */
+ gdk_region_offset (copy_area, -dx, -dy);
+ gdk_region_intersect (copy_area, impl_window->update_area);
+ gdk_region_subtract (impl_window->update_area, copy_area);
+ gdk_region_offset (copy_area, dx, dy);
+ gdk_region_union (impl_window->update_area, copy_area);
+ }
+
+ /* Invalidate affected part in the parent window
+ * (no higher window should be affected)
+ * We also invalidate any children in that area, which could include
+ * this window if it still overlaps that area.
+ */
+ gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
+
+
+ gdk_region_destroy (old_region);
+ gdk_region_destroy (new_region);
+ gdk_region_destroy (copy_area);
+ }
+
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
}
+
+
/**
* gdk_window_move:
* @window: a #GdkWindow
gint x,
gint y)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, -1, -1);
-}
+ gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
+}
/**
* gdk_window_resize:
gint width,
gint height)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, FALSE, 0, 0, width, height);
+ gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
}
gint width,
gint height)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, width, height);
+ gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
}
gint dy)
{
GdkWindowObject *private = (GdkWindowObject *) window;
+ GdkWindowObject *impl_window;
+ GdkRegion *source_area, *copy_area, *noncopy_area;
+ GdkRectangle copy_rect;
+ GdkGC *tmp_gc;
+ GList *tmp_list;
g_return_if_fail (GDK_IS_WINDOW (window));
if (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->scroll (window, dx, dy);
+ /* First move all child windows, without causing invalidation */
+
+ tmp_list = private->children;
+ while (tmp_list)
+ {
+ GdkWindow *child = GDK_WINDOW (tmp_list->data);
+ GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
+
+ if (child_obj->impl == private->impl)
+ {
+ /* Just update the positions, the bits will move with the copy */
+ child_obj->x += dx;
+ child_obj->y += dy;
+ }
+ else
+ {
+ /* Native window, need to move it */
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, child_obj->x + dx, child_obj->y + dy, -1, -1);
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ recompute_visible_regions (private, FALSE, TRUE);
+
+ /* Then copy the actual bits of the window w/ child windows */
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ /* Calculate the area that can be gotten by copying the old area */
+ copy_area = gdk_region_copy (private->clip_region);
+ gdk_region_offset (copy_area, dx, dy);
+ gdk_region_intersect (copy_area, private->clip_region);
+
+ /* And the rest need to be invalidated */
+ noncopy_area = gdk_region_copy (private->clip_region);
+ gdk_region_subtract (noncopy_area, copy_area);
+
+ /* Get window clip and convert to real window coords, this
+ area is moved and we queue translations for all expose events
+ to it that will be sent before the copy operation */
+ /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
+ if (!gdk_window_is_offscreen (impl_window))
+ {
+ source_area = gdk_region_copy (private->clip_region);
+ /* convert from window coords to real parent */
+ gdk_region_offset (source_area, private->abs_x, private->abs_y);
+ _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
+ gdk_region_destroy (source_area);
+ }
+
+ /* convert from window coords to real parent */
+ gdk_region_offset (copy_area, private->abs_x, private->abs_y);
+ gdk_region_get_clipbox (copy_area, ©_rect);
+ tmp_gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+ gdk_gc_set_clip_region (tmp_gc, copy_area);
+ gdk_draw_drawable (private->impl,
+ tmp_gc,
+ private->impl,
+ copy_rect.x-dx, copy_rect.y-dy,
+ copy_rect.x, copy_rect.y,
+ copy_rect.width, copy_rect.height);
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+
+ /* Move the current invalid region for the copy area */
+ if (private->update_area)
+ {
+ /* Convert from target to source */
+ gdk_region_offset (copy_area, -dx, -dy);
+ gdk_region_intersect (copy_area, impl_window->update_area);
+ gdk_region_subtract (impl_window->update_area, copy_area);
+ gdk_region_offset (copy_area, dx, dy);
+ gdk_region_union (impl_window->update_area, copy_area);
+ }
+
+ /* Invalidate not copied regions */
+ gdk_window_invalidate_region (window, noncopy_area, TRUE);
+
+ gdk_region_destroy (noncopy_area);
+ gdk_region_destroy (copy_area);
+
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
}
/**
gint dy)
{
GdkWindowObject *private = (GdkWindowObject *) window;
+ GdkWindowObject *impl_window;
+ GdkRegion *source_area;
+ GdkRegion *nocopy_area;
+ GdkRegion *copy_area;
+ GdkRegion *moving_invalid_region;
+ GdkRectangle copy_rect;
+ GdkGC *tmp_gc;
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (region != NULL);
if (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_region (window, region, dx, dy);
+ impl_window = gdk_window_get_impl_window (private);
+
+ /* compute source regions */
+ source_area = gdk_region_copy (region);
+ gdk_region_intersect (source_area, private->clip_region_with_children);
+
+ /* compute destination regions */
+ copy_area = gdk_region_copy (source_area);
+ gdk_region_offset (copy_area, dx, dy);
+ gdk_region_intersect (copy_area, private->clip_region_with_children);
+
+ /* Move the current invalid region for the copy area */
+ if (impl_window->update_area)
+ {
+ moving_invalid_region = gdk_region_copy (copy_area);
+ gdk_region_offset (moving_invalid_region, private->abs_x - dx, private->abs_y - dy);
+ gdk_region_intersect (moving_invalid_region, impl_window->update_area);
+ gdk_region_subtract (impl_window->update_area, moving_invalid_region);
+ gdk_region_offset (moving_invalid_region, dx, dy);
+ gdk_region_union (impl_window->update_area, moving_invalid_region);
+ gdk_region_destroy (moving_invalid_region);
+ }
+
+ /* invalidate parts of the region not covered by the copy */
+ nocopy_area = gdk_region_copy (region);
+ gdk_region_offset (nocopy_area, dx, dy);
+ gdk_region_subtract (nocopy_area, copy_area);
+ gdk_window_invalidate_region (window, nocopy_area, FALSE);
+ gdk_region_destroy (nocopy_area);
+
+ /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
+ if (!gdk_window_is_offscreen (impl_window))
+ {
+ gdk_region_offset (source_area, private->abs_x, private->abs_y);
+ _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
+ }
+
+ gdk_region_offset (copy_area, private->abs_x, private->abs_y);
+ gdk_region_get_clipbox (copy_area, ©_rect);
+ tmp_gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+ gdk_gc_set_clip_region (tmp_gc, copy_area);
+ gdk_draw_drawable (private->impl,
+ tmp_gc,
+ private->impl,
+ copy_rect.x-dx, copy_rect.y-dy,
+ copy_rect.x, copy_rect.y,
+ copy_rect.width, copy_rect.height);
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+
+ gdk_region_destroy (source_area);
+ gdk_region_destroy (copy_area);
}
/**
const GdkColor *color)
{
GdkWindowObject *private;
+ GdkColormap *colormap = gdk_drawable_get_colormap (window);
g_return_if_fail (GDK_IS_WINDOW (window));
private = (GdkWindowObject *) window;
+
+ private->bg_color = *color;
+ gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+ if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_unref (private->bg_pixmap);
+
+ private->bg_pixmap = NULL;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, color);
+ if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
}
/**
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, pixmap, parent_relative);
+ if (pixmap && !gdk_drawable_get_colormap (pixmap))
+ {
+ g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+ return;
+ }
+
+ if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_unref (private->bg_pixmap);
+
+ if (parent_relative)
+ private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
+ else if (pixmap)
+ private->bg_pixmap = g_object_ref (pixmap);
+ else
+ private->bg_pixmap = GDK_NO_BG;
+
+ if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
}
/**
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+ if (private->cursor)
+ {
+ gdk_cursor_unref (private->cursor);
+ private->cursor = NULL;
+ }
+
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ if (cursor)
+ private->cursor = gdk_cursor_ref (cursor);
+
+ /* TODO: Track this via pointer_window
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+ */
+ }
}
/**
if (!GDK_WINDOW_DESTROYED (window))
{
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
- width, height,
- depth);
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
+ width, height,
+ depth);
+ else
+ {
+ if (x)
+ *x = private->x;
+ if (y)
+ *y = private->y;
+ if (width)
+ *width = private->width;
+ if (height)
+ *height = private->height;
+ if (depth)
+ *depth = private->depth;
+ }
}
}
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
private = (GdkWindowObject *) window;
+
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
- return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
+ if (x)
+ *x += private->abs_x;
+ if (y)
+ *y += private->abs_y;
+
+ return TRUE;
}
/**
private = (GdkWindowObject *) window;
- return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+ if (gdk_window_has_impl (private))
+ return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+
+ return FALSE;
}
/**
gint height)
{
GdkWindowObject *private;
-
+
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_IS_DRAWABLE (drawable));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
window_get_size_rectangle (GdkWindow *window,
GdkRectangle *rect)
{
+ GdkWindowObject *private = (GdkWindowObject *) window;
+
rect->x = rect->y = 0;
- gdk_drawable_get_size (GDK_DRAWABLE (window), &rect->width, &rect->height);
+ rect->width = private->width;
+ rect->height = private->height;
}
/* Calculates the real clipping region for a window, in window coordinates,
* taking into account other windows, gc clip region and gc clip mask.
*/
-static GdkRegion *
+GdkRegion *
_gdk_window_calculate_full_clip_region (GdkWindow *window,
GdkWindow *base_window,
- GdkGC *gc,
- gboolean do_children,
- gint *base_x_offset,
- gint *base_y_offset)
+ gboolean do_children,
+ gint *base_x_offset,
+ gint *base_y_offset)
{
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
GdkRectangle visible_rect;
window_get_size_rectangle (window, &visible_rect);
- /* windows that a redirection has ben setup for need to be considered
- * fully visible, in order to avoid missing redirected paint ops
- * anywhere in the window area.
- */
- if (private->redirect && private->redirect->redirected == private)
- return gdk_region_rectangle (&visible_rect);
-
/* real_clip_region is in window coordinates */
real_clip_region = gdk_region_rectangle (&visible_rect);
parentwin = lastwin->parent;
/* Remove the areas of all overlapping windows above parentwin in the hiearachy */
- for (; parentwin != NULL && (parentwin == private || lastwin != (GdkWindowObject *)base_window);
+ for (; parentwin != NULL &&
+ (parentwin == private || lastwin != (GdkWindowObject*) base_window);
lastwin = parentwin, parentwin = lastwin->parent)
{
GList *cur;
GdkRectangle real_clip_rect;
-
+ gboolean is_offscreen;
+
if (parentwin != private)
{
x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
}
-
+
+ is_offscreen = gdk_window_is_offscreen (parentwin);
+
/* children is ordered in reverse stack order */
- for (cur = GDK_WINDOW_OBJECT (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
+ for (cur = parentwin->children;
+ cur && cur->data != lastwin;
+ cur = cur->next)
{
GdkWindow *child = cur->data;
GdkWindowObject *child_private = (GdkWindowObject *)child;
-
+
if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
continue;
+ /* Ignore offscreen children, as they don't draw in their parent and
+ * don't take part in the clipping */
+ if (gdk_window_is_offscreen (child_private))
+ continue;
+
window_get_size_rectangle (child, &visible_rect);
/* Convert rect to "window" coords */
gdk_region_destroy (tmpreg);
}
- if (gc)
- {
- GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
-
- if (clip_region)
- {
- /* clip_region is relative to gc clip origin which is relative to the window */
- /* offset it to window relative: */
- tmpreg = gdk_region_copy (clip_region);
- gdk_region_offset (real_clip_region,
- gc->clip_x_origin,
- gc->clip_y_origin);
- /* Intersect it with window hierarchy cliprect: */
- gdk_region_intersect (real_clip_region, tmpreg);
- gdk_region_destroy (tmpreg);
- }
- }
-
if (base_x_offset)
*base_x_offset = x_offset;
if (base_y_offset)
return real_clip_region;
}
-static void
-gdk_window_add_damage (GdkWindow *toplevel,
- GdkRegion *damaged_region)
+void
+_gdk_window_add_damage (GdkWindow *toplevel,
+ GdkRegion *damaged_region)
{
GdkDisplay *display;
GdkEvent event = { 0, };
}
static void
-setup_redirect_clip (GdkWindow *window,
- GdkGC *gc,
- GdkWindowClipData *data)
+gdk_window_redirect_free (GdkWindowRedirect *redirect)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkRegion *visible_region;
- GdkRectangle dest_rect;
- GdkRegion *tmpreg;
- GdkWindow *toplevel;
+ g_object_unref (redirect->pixmap);
+ g_free (redirect);
+}
- data->old_region = _gdk_gc_get_clip_region (gc);
- if (data->old_region)
- data->old_region = gdk_region_copy (data->old_region);
+static void
+convert_coords_to_child (GdkWindowObject *child,
+ double x, double y,
+ double *child_x, double *child_y)
+{
+ *child_x = x - child->x;
+ *child_y = y - child->y;
- data->old_clip_x_origin = gc->clip_x_origin;
- data->old_clip_y_origin = gc->clip_y_origin;
+ if (child->offscreen_hooks)
+ child->offscreen_hooks->from_parent ((GdkWindow *)child, x, y, child_x, child_y);
+}
- toplevel = GDK_WINDOW (private->redirect->redirected);
+static gboolean
+point_in_window (GdkWindowObject *window,
+ double x, double y)
+{
+ int w, h;
- /* Get the clip region for gc clip rect + window hierarchy in
- window relative coords */
- visible_region =
- _gdk_window_calculate_full_clip_region (window, toplevel,
- gc, TRUE,
- &data->x_offset,
- &data->y_offset);
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+
+ return
+ x >= 0 && x < w &&
+ y >= 0 && y < h;
+}
- /* Compensate for the source pos/size */
- data->x_offset -= private->redirect->src_x;
- data->y_offset -= private->redirect->src_y;
- dest_rect.x = -data->x_offset;
- dest_rect.y = -data->y_offset;
- dest_rect.width = private->redirect->width;
- dest_rect.height = private->redirect->height;
- tmpreg = gdk_region_rectangle (&dest_rect);
- gdk_region_intersect (visible_region, tmpreg);
- gdk_region_destroy (tmpreg);
+static void
+convert_toplevel_coords_to_window (GdkWindow *window,
+ gdouble toplevel_x,
+ gdouble toplevel_y,
+ gdouble *window_x,
+ gdouble *window_y)
+{
+ GdkWindowObject *private;
+ gdouble x, y;
+ GList *children, *l;
- /* Compensate for the dest pos */
- data->x_offset += private->redirect->dest_x;
- data->y_offset += private->redirect->dest_y;
+ private = GDK_WINDOW_OBJECT (window);
+
+ x = toplevel_x;
+ y = toplevel_y;
- gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+ children = NULL;
+ while (private->parent != NULL &&
+ (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+ {
+ children = g_list_prepend (children, private);
+ private = private->parent;
+ }
- /* offset clip and tiles from window coords to pixmaps coords */
- gdk_gc_offset (gc, -data->x_offset, -data->y_offset);
+ for (l = children; l != NULL; l = l->next)
+ convert_coords_to_child (l->data, x, y, &x, &y);
+
+ g_list_free (children);
+
+ *window_x = x;
+ *window_y = y;
+}
+
+GdkWindow *
+_gdk_window_find_descendant_at (GdkWindow *toplevel,
+ double x, double y,
+ double *found_x,
+ double *found_y)
+{
+ GdkWindowObject *private, *sub;
+ double child_x, child_y;
+ GList *l;
- /* Offset region to abs coords and add to damage */
- gdk_region_offset (visible_region, data->x_offset, data->y_offset);
- gdk_window_add_damage (toplevel, visible_region);
+ private = (GdkWindowObject *)toplevel;
- gdk_region_destroy (visible_region);
+ if (point_in_window (private, x, y))
+ {
+ do
+ {
+ /* Children is ordered in reverse stack order, i.e. first is topmost */
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ sub = l->data;
+
+ if (!GDK_WINDOW_IS_MAPPED (sub))
+ continue;
+
+ convert_coords_to_child (sub,
+ x, y,
+ &child_x, &child_y);
+ if (point_in_window (sub, child_x, child_y))
+ {
+ x = child_x;
+ y = child_y;
+ private = sub;
+ break;
+ }
+ }
+ }
+ while (l != NULL);
+ }
+ else
+ {
+ /* Not in window at all */
+ private = NULL;
+ }
+
+ if (found_x)
+ *found_x = x;
+ if (found_y)
+ *found_y = y;
+
+ return (GdkWindow *)private;
}
-static void
-reset_redirect_clip (GdkWindow *offscreen,
- GdkGC *gc,
- GdkWindowClipData *data)
+static const guint type_masks[] = {
+ GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
+ GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
+ GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
+ GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
+ GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
+ GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
+ GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
+ GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
+ GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
+ GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
+ GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
+ GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
+ GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
+ GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
+ GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
+ GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
+ GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
+ GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
+ GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
+ GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
+ GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
+ GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
+ GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
+ GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
+ GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
+ GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
+ 0, /* GDK_WINDOW_STATE = 32 */
+ 0, /* GDK_SETTING = 33 */
+ 0, /* GDK_OWNER_CHANGE = 34 */
+ 0, /* GDK_GRAB_BROKEN = 35 */
+ 0, /* GDK_DAMAGE = 36 */
+};
+G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
+
+/* send motion events if the right buttons are down */
+static guint
+update_evmask_for_button_motion (guint evmask,
+ GdkModifierType mask)
+{
+ if (evmask & GDK_BUTTON_MOTION_MASK &&
+ mask & (GDK_BUTTON1_MASK |
+ GDK_BUTTON2_MASK |
+ GDK_BUTTON3_MASK |
+ GDK_BUTTON4_MASK |
+ GDK_BUTTON5_MASK))
+ evmask |= GDK_POINTER_MOTION_MASK;
+
+ if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
+ (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
+ (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
+ evmask |= GDK_POINTER_MOTION_MASK;
+
+ return evmask;
+}
+
+static GdkWindow *
+get_target_window_for_pointer_event (GdkDisplay *display,
+ GdkWindow *window,
+ GdkEventType type,
+ GdkModifierType mask)
{
- /* offset back */
- gdk_gc_offset (gc, data->x_offset, data->y_offset);
+ guint evmask;
+ gboolean crossing_event;
+ GdkWindow *w, *grab_window;
+
+ /* crossing events don't propagate up like other types of events */
+ crossing_event = (type == GDK_ENTER_NOTIFY || type == GDK_LEAVE_NOTIFY);
+
+ if ((display->pointer_grab.window != NULL && !display->pointer_grab.owner_events) ||
+ (type == GDK_BUTTON_RELEASE && display->pointer_grab.grab_one_pointer_release_event))
+ {
+ evmask = display->pointer_grab.event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
+
+ if (type == GDK_BUTTON_RELEASE &&
+ display->pointer_grab.grab_one_pointer_release_event)
+ {
+ grab_window = display->pointer_grab.grab_one_pointer_release_event;
+ display->pointer_grab.grab_one_pointer_release_event = NULL;
+ }
+ else
+ grab_window = display->pointer_grab.window;
+
+ if ((evmask & type_masks[type]) &&
+ (!crossing_event || window == grab_window))
+ return grab_window;
+ else
+ return NULL;
+ }
+
+ w = window;
+ while (w != NULL)
+ {
+ evmask = GDK_WINDOW_OBJECT(window)->event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
+
+ if (evmask & type_masks[type])
+ return w;
- /* reset old clip */
- gdk_gc_set_clip_region (gc, data->old_region);
- if (data->old_region)
- gdk_region_destroy (data->old_region);
- gdk_gc_set_clip_origin (gc, data->old_clip_x_origin, data->old_clip_y_origin);
+ if (crossing_event)
+ break;
+
+ w = gdk_window_get_parent (w);
+ }
+
+ if (display->pointer_grab.window != NULL &&
+ display->pointer_grab.owner_events)
+ {
+ evmask = display->pointer_grab.event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
+
+ if ((evmask & type_masks[type]) &&
+ (!crossing_event || window == display->pointer_grab.window))
+ return display->pointer_grab.window;
+ else
+ return NULL;
+ }
+
+ return NULL;
}
-static void
-gdk_window_redirect_free (GdkWindowRedirect *redirect)
+
+static gboolean
+is_button_type (GdkEventType type)
{
- g_object_unref (redirect->pixmap);
- g_free (redirect);
+ return type == GDK_BUTTON_PRESS ||
+ type == GDK_2BUTTON_PRESS ||
+ type == GDK_3BUTTON_PRESS ||
+ type == GDK_BUTTON_RELEASE ||
+ type == GDK_SCROLL;
+}
+
+static gboolean
+is_motion_type (GdkEventType type)
+{
+ return type == GDK_MOTION_NOTIFY ||
+ type == GDK_ENTER_NOTIFY ||
+ type == GDK_LEAVE_NOTIFY;
+}
+
+static GdkWindow *
+find_common_ancestor (GdkWindow *win1,
+ GdkWindow *win2)
+{
+ GdkWindowObject *tmp;
+ GList *path1 = NULL, *path2 = NULL;
+ GList *list1, *list2;
+
+ tmp = GDK_WINDOW_OBJECT (win1);
+ while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+ {
+ path1 = g_list_prepend (path1, tmp);
+ tmp = tmp->parent;
+ }
+
+ tmp = GDK_WINDOW_OBJECT (win2);
+ while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+ {
+ path2 = g_list_prepend (path2, tmp);
+ tmp = tmp->parent;
+ }
+
+ list1 = path1;
+ list2 = path2;
+ tmp = NULL;
+ while (list1 && list2 && (list1->data == list2->data))
+ {
+ tmp = (GdkWindowObject *)list1->data;
+ list1 = g_list_next (list1);
+ list2 = g_list_next (list2);
+ }
+ g_list_free (path1);
+ g_list_free (path2);
+
+ return GDK_WINDOW (tmp);
+}
+
+GdkEvent *
+_gdk_make_event (GdkWindow *window,
+ GdkEventType type,
+ GdkEvent *event_in_queue,
+ gboolean before_event)
+{
+ GdkEvent *event = gdk_event_new (type);
+ guint32 the_time;
+ GdkModifierType the_state;
+
+ the_time = gdk_event_get_time (event_in_queue);
+ gdk_event_get_state (event_in_queue, &the_state);
+
+ event->any.window = g_object_ref (window);
+ event->any.send_event = FALSE;
+
+ switch (type)
+ {
+ case GDK_MOTION_NOTIFY:
+ event->motion.time = the_time;
+ event->motion.axes = NULL;
+ event->motion.state = the_state;
+ break;
+
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ event->button.time = the_time;
+ event->button.axes = NULL;
+ event->button.state = the_state;
+ break;
+
+ case GDK_SCROLL:
+ event->scroll.time = the_time;
+ event->scroll.state = the_state;
+ break;
+
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ event->key.time = the_time;
+ event->key.state = the_state;
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ event->crossing.time = the_time;
+ event->crossing.state = the_state;
+ break;
+
+ case GDK_PROPERTY_NOTIFY:
+ event->property.time = the_time;
+ event->property.state = the_state;
+ break;
+
+ case GDK_SELECTION_CLEAR:
+ case GDK_SELECTION_REQUEST:
+ case GDK_SELECTION_NOTIFY:
+ event->selection.time = the_time;
+ break;
+
+ case GDK_PROXIMITY_IN:
+ case GDK_PROXIMITY_OUT:
+ event->proximity.time = the_time;
+ break;
+
+ case GDK_DRAG_ENTER:
+ case GDK_DRAG_LEAVE:
+ case GDK_DRAG_MOTION:
+ case GDK_DRAG_STATUS:
+ case GDK_DROP_START:
+ case GDK_DROP_FINISHED:
+ event->dnd.time = the_time;
+ break;
+
+ case GDK_FOCUS_CHANGE:
+ case GDK_CONFIGURE:
+ case GDK_MAP:
+ case GDK_UNMAP:
+ case GDK_CLIENT_EVENT:
+ case GDK_VISIBILITY_NOTIFY:
+ case GDK_NO_EXPOSE:
+ case GDK_DELETE:
+ case GDK_DESTROY:
+ case GDK_EXPOSE:
+ default:
+ break;
+ }
+
+ if (event_in_queue)
+ {
+ if (before_event)
+ _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
+ else
+ _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
+ }
+ else
+ _gdk_event_queue_append (gdk_drawable_get_display (window), event);
+
+ return event;
+}
+
+/* The coordinates are in the toplevel window that src/dest are in.
+ * src and dest are always (if != NULL) in the same toplevel, as
+ * we get a leave-notify and set the window_under_pointer to null
+ * before crossing to another toplevel.
+ */
+void
+_gdk_syntesize_crossing_events (GdkDisplay *display,
+ GdkWindow *src,
+ GdkWindow *dest,
+ GdkCrossingMode mode,
+ gint toplevel_x,
+ gint toplevel_y,
+ GdkModifierType mask,
+ guint32 time_,
+ gboolean do_first,
+ gboolean do_last)
+{
+ GdkWindow *c;
+ GdkWindow *win, *last, *next;
+ GdkEvent *event;
+ GList *path, *list;
+ gboolean non_linear;
+ GdkWindow *a;
+ GdkWindow *b;
+ GdkWindow *event_win;
+
+ /* TODO: Don't send events to toplevel, as we get those from the windowing system */
+
+ a = src;
+ b = dest;
+ if (a == b)
+ return; /* No crossings generated between src and dest */
+
+ c = find_common_ancestor (a, b);
+ non_linear = (c != a) && (c != b);
+
+ if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
+ {
+ /* Traverse up from a to (excluding) c sending leave events */
+
+ event_win = get_target_window_for_pointer_event (display, a, GDK_LEAVE_NOTIFY, mask);
+ if (do_first && event_win)
+ {
+ event = _gdk_make_event (event_win, GDK_LEAVE_NOTIFY, NULL, FALSE);
+ event->crossing.time = time_;
+ event->crossing.subwindow = NULL;
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->crossing.x, &event->crossing.y);
+ event->crossing.x_root = toplevel_x;
+ event->crossing.y_root = toplevel_y;
+ event->crossing.mode = mode;
+ if (non_linear)
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ else if (c == a)
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ else
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ event->crossing.focus = FALSE;
+ event->crossing.state = mask;
+ }
+
+ if (c != a)
+ {
+ last = a;
+ win = GDK_WINDOW (GDK_WINDOW_OBJECT (a)->parent);
+ while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+ {
+ event_win = get_target_window_for_pointer_event (display, win, GDK_LEAVE_NOTIFY, mask);
+ if (event_win)
+ {
+ event = _gdk_make_event (event_win, GDK_LEAVE_NOTIFY, NULL, FALSE);
+ event->crossing.time = time_;
+ event->crossing.subwindow = g_object_ref (last);
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->crossing.x, &event->crossing.y);
+ event->crossing.x_root = toplevel_x;
+ event->crossing.y_root = toplevel_y;
+ event->crossing.mode = mode;
+ if (non_linear)
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ else
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ event->crossing.focus = FALSE;
+ event->crossing.state = mask;
+ }
+ last = win;
+ win = GDK_WINDOW (GDK_WINDOW_OBJECT (win)->parent);
+ }
+ }
+ }
+
+ if (b) /* Might not be a dest, e.g. if we're moving out of the window */
+ {
+ /* Traverse down from c to b */
+ if (c != b)
+ {
+ path = NULL;
+ win = GDK_WINDOW (GDK_WINDOW_OBJECT (b)->parent);
+ while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+ {
+ path = g_list_prepend (path, win);
+ win = GDK_WINDOW( GDK_WINDOW_OBJECT (win)->parent);
+ }
+
+ list = path;
+ while (list)
+ {
+ win = (GdkWindow *)list->data;
+ list = g_list_next (list);
+ if (list)
+ next = (GdkWindow *)list->data;
+ else
+ next = b;
+
+ event_win = get_target_window_for_pointer_event (display, win, GDK_ENTER_NOTIFY, mask);
+ if (event_win)
+ {
+ event = _gdk_make_event (event_win, GDK_ENTER_NOTIFY, NULL, FALSE);
+ event->crossing.time = time_;
+ event->crossing.subwindow = g_object_ref (next);
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->crossing.x, &event->crossing.y);
+ event->crossing.x_root = toplevel_x;
+ event->crossing.y_root = toplevel_y;
+ event->crossing.mode = mode;
+ if (non_linear)
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ else
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ event->crossing.focus = FALSE;
+ event->crossing.state = mask;
+ }
+ }
+ g_list_free (path);
+ }
+
+ event_win = get_target_window_for_pointer_event (display, b, GDK_ENTER_NOTIFY, mask);
+ if (do_last && event_win)
+ {
+ event = _gdk_make_event (event_win, GDK_ENTER_NOTIFY, NULL, FALSE);
+ event->crossing.time = time_;
+ event->crossing.subwindow = NULL;
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->crossing.x, &event->crossing.y);
+ event->crossing.x_root = toplevel_x;
+ event->crossing.y_root = toplevel_y;
+ event->crossing.mode = mode;
+ if (non_linear)
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ else if (c == a)
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ else
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ event->crossing.focus = FALSE;
+ event->crossing.state = mask;
+ }
+ }
+
+}
+
+static GdkWindow *
+get_toplevel (GdkWindow *w)
+{
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
+
+ while (private->parent != NULL &&
+ (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+ private = private->parent;
+
+ return GDK_WINDOW (private);
+}
+
+void
+_gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
+{
+ GdkDisplay *display;
+ GdkWindow *changed_toplevel;
+ GdkWindow *pointer_toplevel;
+ GdkWindow *new_window_under_pointer;
+
+ changed_toplevel = get_toplevel (changed_window);
+
+ display = gdk_drawable_get_display (changed_window);
+ if (display->pointer_info.window_under_pointer)
+ {
+ pointer_toplevel = get_toplevel (display->pointer_info.window_under_pointer);
+
+ if (pointer_toplevel == changed_toplevel)
+ {
+ new_window_under_pointer =
+ _gdk_window_find_descendant_at (pointer_toplevel,
+ display->pointer_info.toplevel_x,
+ display->pointer_info.toplevel_y,
+ NULL, NULL);
+ if (new_window_under_pointer !=
+ display->pointer_info.window_under_pointer)
+ {
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_info.window_under_pointer,
+ new_window_under_pointer,
+ GDK_CROSSING_NORMAL,
+ display->pointer_info.toplevel_x,
+ display->pointer_info.toplevel_y,
+ display->pointer_info.state,
+ GDK_CURRENT_TIME,
+ TRUE, TRUE);
+
+ if (display->pointer_info.window_under_pointer)
+ g_object_unref (display->pointer_info.window_under_pointer);
+ display->pointer_info.window_under_pointer = NULL;
+ if (new_window_under_pointer)
+ display->pointer_info.window_under_pointer = g_object_ref (new_window_under_pointer);
+ }
+ }
+ }
+}
+
+static gboolean
+proxy_pointer_event (GdkDisplay *display,
+ GdkWindow *pointer_window,
+ gdouble toplevel_x,
+ gdouble toplevel_y,
+ GdkEvent *source_event)
+{
+ GdkWindow *event_window;
+ GdkWindow *event_win, *cursor_window;
+ gboolean crossing_event;
+ gboolean sent_motion;
+ GdkEvent *event;
+ guint state;
+ guint32 time_;
+
+ event_window = source_event->any.window;
+
+ gdk_event_get_state (source_event, &state);
+ time_ = gdk_event_get_time (source_event);
+
+ crossing_event =
+ source_event->type == GDK_ENTER_NOTIFY ||
+ source_event->type == GDK_LEAVE_NOTIFY;
+
+ if (crossing_event)
+ {
+ GdkEventCrossing *crossing = &source_event->crossing;
+
+ if (crossing->mode == GDK_CROSSING_GRAB)
+ {
+ if (crossing->type == GDK_LEAVE_NOTIFY &&
+ display->pointer_info.window_under_pointer != NULL)
+ {
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_info.window_under_pointer,
+ event_window,
+ GDK_CROSSING_GRAB,
+ toplevel_x, toplevel_y, state, time_,
+ TRUE, FALSE);
+ }
+
+ if (crossing->type == GDK_ENTER_NOTIFY &&
+ display->pointer_grab.window != NULL)
+ {
+ _gdk_syntesize_crossing_events (display,
+ event_window,
+ display->pointer_grab.window,
+ GDK_CROSSING_GRAB,
+ toplevel_x, toplevel_y, state, time_,
+ FALSE, TRUE);
+ }
+ }
+
+ if (crossing->mode == GDK_CROSSING_UNGRAB)
+ {
+ if (crossing->type == GDK_LEAVE_NOTIFY &&
+ display->pointer_grab.window != NULL)
+ {
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_grab.window,
+ event_window,
+ GDK_CROSSING_UNGRAB,
+ toplevel_x, toplevel_y, state, time_,
+ TRUE, FALSE);
+ }
+
+ if (crossing->type == GDK_ENTER_NOTIFY &&
+ display->pointer_info.window_under_pointer != NULL)
+ {
+ _gdk_syntesize_crossing_events (display,
+ event_window,
+ display->pointer_info.window_under_pointer,
+ GDK_CROSSING_UNGRAB,
+ toplevel_x, toplevel_y, state, time_,
+ FALSE, TRUE);
+ }
+ }
+ }
+
+ cursor_window = pointer_window;
+ if (display->pointer_grab.window &&
+ (pointer_window == NULL ||
+ !is_parent_of (display->pointer_grab.window, pointer_window)))
+ cursor_window = display->pointer_grab.window;
+
+ /* TODO: set cursor from cursor_window, or grab cursor */
+
+ sent_motion = FALSE;
+ if (!crossing_event &&
+ (display->pointer_info.window_under_pointer == pointer_window ||
+ (display->pointer_grab.window != NULL &&
+ !display->pointer_grab.owner_events)))
+ {
+ /* send motion events */
+ event_win = get_target_window_for_pointer_event (display, pointer_window, GDK_MOTION_NOTIFY, state);
+ if (event_win)
+ {
+ sent_motion = TRUE;
+ event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
+ event->motion.time = time_;
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->motion.x, &event->motion.y);
+ event->motion.x_root = toplevel_x; /* TODO: right? */
+ event->motion.y_root = toplevel_y;
+ event->motion.state = state;
+ event->motion.is_hint = FALSE;
+ event->motion.device = NULL;
+ if (source_event && source_event->type == GDK_MOTION_NOTIFY)
+ event->motion.device = source_event->motion.device;
+ }
+ }
+
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_info.window_under_pointer,
+ pointer_window,
+ GDK_CROSSING_NORMAL,
+ toplevel_x, toplevel_y,
+ state, time_,
+ TRUE, TRUE);
+
+ /* unlink move event from parent if we sent a motion event */
+ return source_event->type == GDK_MOTION_NOTIFY && sent_motion;
+}
+
+static gboolean
+proxy_button_event (GdkWindow *pointer_window,
+ gdouble toplevel_x,
+ gdouble toplevel_y,
+ GdkEvent *source_event)
+{
+ GdkWindow *event_win;
+ GdkEvent *event;
+ guint state;
+ guint32 time_;
+ GdkEventType type;
+ GdkDisplay *display;
+
+ type = source_event->any.type;
+ gdk_event_get_state (source_event, &state);
+ time_ = gdk_event_get_time (source_event);
+ display = gdk_drawable_get_display (source_event->any.window);
+
+ if ((type == GDK_BUTTON_PRESS || type == GDK_SCROLL) &&
+ pointer_window != NULL &&
+ display->pointer_grab.window == source_event->any.window &&
+ display->pointer_grab.implicit &&
+ !display->pointer_grab.converted_implicit)
+ {
+ if (pointer_window != source_event->any.window)
+ _gdk_display_set_has_pointer_grab (display,
+ pointer_window,
+ display->pointer_grab.native_window,
+ display->pointer_grab.owner_events,
+ gdk_window_get_events (pointer_window),
+ display->pointer_grab.serial,
+ display->pointer_grab.time,
+ display->pointer_grab.implicit);
+ display->pointer_grab.converted_implicit = TRUE;
+ }
+
+ event_win = get_target_window_for_pointer_event (display,
+ pointer_window,
+ type,
+ state);
+
+ if (event_win == NULL)
+ return TRUE;
+
+ if (event_win != source_event->any.window)
+ {
+ event = _gdk_make_event (event_win, type, source_event, FALSE);
+
+ switch (type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ event->button.button = source_event->button.button;
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->button.x, &event->button.y);
+ event->button.x_root = toplevel_x;
+ event->button.y_root = toplevel_y;
+ event->button.state = state;
+ event->button.device = source_event->button.device;
+
+ if (type == GDK_BUTTON_PRESS)
+ _gdk_event_button_generate (display, event);
+ return TRUE;
+
+ case GDK_SCROLL:
+ event->scroll.direction = source_event->scroll.direction;
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->scroll.x, &event->scroll.y);
+ event->scroll.x_root = toplevel_x;
+ event->scroll.y_root = toplevel_y;
+ event->scroll.state = state;
+ event->scroll.device = source_event->scroll.device;
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* Same window as original window, keep the event */
+ if (source_event->type == GDK_BUTTON_PRESS)
+ _gdk_event_button_generate (display, source_event);
+ return FALSE;
+ }
+}
+
+void
+_gdk_windowing_got_event (GdkDisplay *display,
+ GList *event_link,
+ GdkEvent *event)
+{
+ GdkWindow *event_window;
+ GdkWindow *pointer_window;
+ GdkWindowObject *event_private;
+ gdouble x, y, child_x, child_y;
+ gboolean unlink_event;
+
+ event_window = event->any.window;
+ if (!event_window)
+ return;
+
+ event_private = GDK_WINDOW_OBJECT (event_window);
+
+ if (!(is_button_type (event->type) ||
+ is_motion_type (event->type)))
+ return;
+
+ /* We should only get these events on toplevel windows */
+ g_assert (GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT);
+
+ gdk_event_get_coords (event, &x, &y);
+ pointer_window = _gdk_window_find_descendant_at (event_window, x, y,
+ &child_x,
+ &child_y);
+ unlink_event = FALSE;
+ if (is_motion_type (event->type))
+ unlink_event = proxy_pointer_event (display,
+ pointer_window,
+ x, y,
+ event);
+ else if (is_button_type (event->type))
+ unlink_event = proxy_button_event (pointer_window, x, y,
+ event);
+
+ if (unlink_event)
+ {
+ _gdk_event_queue_remove_link (display, event_link);
+ g_list_free_1 (event_link);
+ gdk_event_free (event);
+ }
+
+
+ /* Store last pointer window and position/state */
+
+ display->pointer_info.toplevel_x = x;
+ display->pointer_info.toplevel_y = y;
+ gdk_event_get_state (event, &display->pointer_info.state);
+
+ if (pointer_window != display->pointer_info.window_under_pointer)
+ {
+ if (display->pointer_info.window_under_pointer)
+ g_object_unref (display->pointer_info.window_under_pointer);
+ display->pointer_info.window_under_pointer = NULL;
+ if (pointer_window)
+ display->pointer_info.window_under_pointer = g_object_ref (pointer_window);
+ }
}
#define __GDK_WINDOW_C__
G_BEGIN_DECLS
-typedef struct _GdkGeometry GdkGeometry;
-typedef struct _GdkWindowAttr GdkWindowAttr;
-typedef struct _GdkPointerHooks GdkPointerHooks;
-typedef struct _GdkWindowRedirect GdkWindowRedirect;
+typedef struct _GdkGeometry GdkGeometry;
+typedef struct _GdkWindowAttr GdkWindowAttr;
+typedef struct _GdkPointerHooks GdkPointerHooks;
+typedef struct _GdkOffscreenChildHooks GdkOffscreenChildHooks;
+typedef struct _GdkWindowRedirect GdkWindowRedirect;
+typedef struct _GdkWindowPaint GdkWindowPaint;
/* Classes of windows.
* InputOutput: Almost every window should be of this type. Such windows
GDK_WINDOW_CHILD,
GDK_WINDOW_DIALOG,
GDK_WINDOW_TEMP,
- GDK_WINDOW_FOREIGN
+ GDK_WINDOW_FOREIGN,
+ GDK_WINDOW_OFFSCREEN
} GdkWindowType;
/* Window attribute mask values.
gint *win_y);
};
+struct _GdkOffscreenChildHooks
+{
+ void (*from_parent) (GdkWindow *offscreen_child,
+ gdouble parent_x,
+ gdouble parent_y,
+ gdouble *child_x,
+ gdouble *child_y);
+ void (*to_parent) (GdkWindow *offscreen_child,
+ gdouble child_x,
+ gdouble child_y,
+ gdouble *parent_x,
+ gdouble *parent_y);
+};
+
typedef struct _GdkWindowObject GdkWindowObject;
typedef struct _GdkWindowObjectClass GdkWindowObjectClass;
guint update_and_descendants_freeze_count;
GdkWindowRedirect *redirect;
+ const GdkOffscreenChildHooks *offscreen_hooks;
+
+ int abs_x, abs_y; /* Absolute offset in impl */
+ gint width, height;
+ GdkRegion *clip_region; /* Clip region (wrt toplevel) in window coords */
+ GdkRegion *clip_region_with_children; /* Clip region in window coords */
+ GdkColormap *colormap;
+ GdkCursor *cursor;
+ gint8 toplevel_window_type;
+
+ GdkWindowPaint *implicit_paint;
+
+ cairo_surface_t *cairo_surface;
};
struct _GdkWindowObjectClass
GdkWindow *gdk_get_default_root_window (void);
-void gdk_window_redirect_to_drawable (GdkWindow *window,
- GdkDrawable *drawable,
- gint src_x, gint src_y,
- gint dest_x, gint dest_y,
- gint width, gint height);
-void gdk_window_remove_redirection (GdkWindow *window);
+/* Offscreen redirection */
+GdkPixmap *gdk_window_get_offscreen_pixmap (GdkWindow *window);
+
+void gdk_window_redirect_to_drawable (GdkWindow *window,
+ GdkDrawable *drawable,
+ gint src_x,
+ gint src_y,
+ gint dest_x,
+ gint dest_y,
+ gint width,
+ gint height);
+void gdk_window_remove_redirection (GdkWindow *window);
+
+void gdk_window_set_offscreen_hooks (GdkWindow *offscreen_window,
+ const GdkOffscreenChildHooks *hooks);
#ifndef GDK_DISABLE_DEPRECATED
#define GDK_ROOT_PARENT() (gdk_get_default_root_window ())
gint y,
gint width,
gint height);
- void (* move_region) (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy);
- void (* scroll) (GdkWindow *window,
- gint dx,
- gint dy);
-
void (* clear_area) (GdkWindow *window,
gint x,
gint y,
void (* set_background) (GdkWindow *window,
const GdkColor *color);
void (* set_back_pixmap) (GdkWindow *window,
- GdkPixmap *pixmap,
- gboolean parent_relative);
+ GdkPixmap *pixmap);
GdkEventMask (* get_events) (GdkWindow *window);
void (* set_events) (GdkWindow *window,
gint (* get_origin) (GdkWindow *window,
gint *x,
gint *y);
- void (* get_offsets) (GdkWindow *window,
- gint *x_offset,
- gint *y_offset);
void (* shape_combine_mask) (GdkWindow *window,
GdkBitmap *mask,
gboolean (* set_static_gravities) (GdkWindow *window,
gboolean use_static);
+
+ /* Called before processing updates for a window. This gives the windowing
+ * layer a chance to save the region for later use in avoiding duplicate
+ * exposes. The return value indicates whether the function has a saved
+ * the region; if the result is TRUE, then the windowing layer is responsible
+ * for destroying the region later.
+ */
+ gboolean (* queue_antiexpose) (GdkWindow *window,
+ GdkRegion *update_area);
};
/* Interface Functions */
GType gdk_window_impl_get_type (void) G_GNUC_CONST;
+/* private definitions from gdkwindow.h */
+
+struct _GdkWindowRedirect
+{
+ GdkWindowObject *redirected;
+ GdkDrawable *pixmap;
+
+ gint src_x;
+ gint src_y;
+ gint dest_x;
+ gint dest_y;
+ gint width;
+ gint height;
+
+ GdkRegion *damage;
+ guint damage_idle;
+};
+
G_END_DECLS
#endif /* __GDK_WINDOW_IMPL_H__ */
}
GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
- gint width,
- gint height,
- gint depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+ gint width,
+ gint height,
+ gint depth)
{
GdkPixmap *pixmap;
GdkDrawableImplQuartz *draw_impl;
}
GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *window,
- const gchar *data,
- gint width,
- gint height)
+_gdk_bitmap_create_from_data (GdkDrawable *window,
+ const gchar *data,
+ gint width,
+ gint height)
{
GdkPixmap *pixmap;
GdkPixmapImplQuartz *impl;
}
GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable *drawable,
- const gchar *data,
- gint width,
- gint height,
- gint depth,
- const GdkColor *fg,
- const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ const GdkColor *fg,
+ const GdkColor *bg)
{
/* FIXME: Implement */
return NULL;
*/
void
gdk_display_pointer_ungrab (GdkDisplay *display,
- guint32 time)
+ guint32 time_)
{
Display *xdisplay;
GdkDisplayX11 *display_x11;
display_x11 = GDK_DISPLAY_X11 (display);
xdisplay = GDK_DISPLAY_XDISPLAY (display);
- _gdk_input_ungrab_pointer (display, time);
- XUngrabPointer (xdisplay, time);
+ _gdk_input_ungrab_pointer (display, time_);
+ XUngrabPointer (xdisplay, time_);
XFlush (xdisplay);
- if (time == GDK_CURRENT_TIME ||
- display_x11->pointer_xgrab_time == GDK_CURRENT_TIME ||
- !XSERVER_TIME_IS_LATER (display_x11->pointer_xgrab_time, time))
- display_x11->pointer_xgrab_window = NULL;
-}
-
-/**
- * gdk_display_pointer_is_grabbed:
- * @display: a #GdkDisplay
- *
- * Test if the pointer is grabbed.
- *
- * Returns: %TRUE if an active X pointer grab is in effect
- *
- * Since: 2.2
- */
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
- g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
-
- return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
- !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
+ if (time_ == GDK_CURRENT_TIME ||
+ display->pointer_grab.time == GDK_CURRENT_TIME ||
+ !XSERVER_TIME_IS_LATER (display->pointer_grab.time, time_))
+ {
+ _gdk_display_unset_has_pointer_grab (display,
+ FALSE,
+ FALSE,
+ time_);
+ }
}
/**
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
Atom clipboard_manager, save_targets;
-
+
+ g_return_if_fail (GDK_WINDOW_IS_X11 (clipboard_window));
+
clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
#include <gdk/gdkdisplay.h>
#include <gdk/gdkkeys.h>
#include <gdk/gdkwindow.h>
+#include <gdk/gdkinternals.h>
#include <gdk/gdk.h> /* For gdk_get_program_class() */
G_BEGIN_DECLS
* (grabs, properties etc.) Otherwise always TRUE. */
gboolean trusted_client;
- /* Information about current pointer and keyboard grabs held by this
- * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window
+ /* Information about current keyboard grabs held by this
+ * client. If gdk_keyboard_xgrab_window
* window is NULL, then the other associated fields are ignored
+ * Pointer grab info is stored in GdkDisplay.
*/
- GdkWindowObject *pointer_xgrab_window;
- gulong pointer_xgrab_serial;
- gboolean pointer_xgrab_owner_events;
- gboolean pointer_xgrab_implicit;
- guint32 pointer_xgrab_time;
GdkWindowObject *keyboard_xgrab_window;
+ GdkWindowObject *keyboard_xgrab_native_window;
gulong keyboard_xgrab_serial;
gboolean keyboard_xgrab_owner_events;
guint32 keyboard_xgrab_time;
/* Alpha mask picture format */
XRenderPictFormat *mask_format;
+
+ /* The offscreen window that has the pointer in it (if any) */
+ GdkWindow *active_offscreen_window;
};
struct _GdkDisplayX11Class
GdkDragContext *new_context;
g_return_val_if_fail (window != NULL, NULL);
+ g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), NULL);
new_context = gdk_drag_context_new ();
new_context->is_source = TRUE;
window_cache = drag_context_find_window_cache (context, screen);
dest = get_client_window_at_coords (window_cache,
- drag_window ?
+ drag_window && GDK_WINDOW_IS_X11 (drag_window) ?
GDK_DRAWABLE_XID (drag_window) : None,
x_root, y_root);
GdkDragContextPrivateX11 *private = PRIVATE_DATA (context);
g_return_val_if_fail (context != NULL, FALSE);
+ g_return_val_if_fail (dest_window == NULL || GDK_WINDOW_IS_X11 (dest_window), FALSE);
private->old_actions = context->actions;
context->actions = possible_actions;
GdkDrawable *impl;
if (GDK_IS_WINDOW (drawable))
- impl = ((GdkPixmapObject *)drawable)->impl;
+ {
+ if (!GDK_WINDOW_IS_X11 (drawable))
+ {
+ /* TODO: At this point we could convert a virtual window
+ to a native one (unless its in an offscreen window) */
+ g_warning (G_STRLOC " drawable is not a native X11 window");
+ return None;
+ }
+
+ impl = ((GdkPixmapObject *)drawable)->impl;
+ }
else if (GDK_IS_PIXMAP (drawable))
impl = ((GdkPixmapObject *)drawable)->impl;
else
impl->cairo_surface = NULL;
}
+void
+_gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+ int width,
+ int height)
+{
+ cairo_xlib_surface_set_size (surface, width, height);
+}
+
+cairo_surface_t *
+_gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height)
+{
+ GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+ GdkVisual *visual;
+
+ visual = gdk_drawable_get_visual (drawable);
+ if (visual)
+ return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
+ impl->xid,
+ GDK_VISUAL_XVISUAL (visual),
+ width, height);
+ else if (gdk_drawable_get_depth (drawable) == 1)
+ return cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
+ impl->xid,
+ GDK_SCREEN_XSCREEN (impl->screen),
+ width, height);
+ else
+ {
+ g_warning ("Using Cairo rendering requires the drawable argument to\n"
+ "have a specified colormap. All windows have a colormap,\n"
+ "however, pixmaps only have colormap by default if they\n"
+ "were created with a non-NULL window argument. Otherwise\n"
+ "a colormap must be set on them with gdk_drawable_set_colormap");
+ return NULL;
+ }
+
+}
+
static cairo_surface_t *
gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
{
if (!impl->cairo_surface)
{
- GdkVisual *visual = NULL;
int width, height;
- visual = gdk_drawable_get_visual (drawable);
-
gdk_drawable_get_size (drawable, &width, &height);
- if (visual)
- impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
- impl->xid,
- GDK_VISUAL_XVISUAL (visual),
- width, height);
- else if (gdk_drawable_get_depth (drawable) == 1)
- impl->cairo_surface = cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
- impl->xid,
- GDK_SCREEN_XSCREEN (impl->screen),
- width, height);
- else
- {
- g_warning ("Using Cairo rendering requires the drawable argument to\n"
- "have a specified colormap. All windows have a colormap,\n"
- "however, pixmaps only have colormap by default if they\n"
- "were created with a non-NULL window argument. Otherwise\n"
- "a colormap must be set on them with gdk_drawable_set_colormap");
- return NULL;
- }
-
- cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
- drawable, gdk_x11_cairo_surface_destroy);
+ impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable, width, height);
+
+ if (impl->cairo_surface)
+ cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
+ drawable, gdk_x11_cairo_surface_destroy);
}
else
cairo_surface_reference (impl->cairo_surface);
GdkEvent *event;
g_return_val_if_fail (window != NULL, NULL);
-
+
XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent,
graphics_expose_predicate, (XPointer) window);
GdkWindow *filter_window;
GdkWindowImplX11 *window_impl = NULL;
gboolean return_val;
- gint xoffset, yoffset;
GdkScreen *screen = NULL;
GdkScreenX11 *screen_x11 = NULL;
GdkToplevelX11 *toplevel = NULL;
if (window != NULL)
{
+ /* Rewrite keyboard grabs to offscreen windows */
+ if ((xevent->type == KeyPress || xevent->type == KeyRelease) &&
+ window_private == display_x11->keyboard_xgrab_native_window)
+ {
+ window_private = display_x11->keyboard_xgrab_window;
+ window = (GdkWindow *) window_private;
+ }
+
window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
/* Move key events on focus window to the real toplevel, and
return_val = TRUE;
- if (window)
- {
- _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
- }
- else
- {
- xoffset = 0;
- yoffset = 0;
- }
-
switch (xevent->type)
{
case KeyPress:
event->scroll.window = window;
event->scroll.time = xevent->xbutton.time;
- event->scroll.x = xevent->xbutton.x + xoffset;
- event->scroll.y = xevent->xbutton.y + yoffset;
+ event->scroll.x = xevent->xbutton.x;
+ event->scroll.y = xevent->xbutton.y;
event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
event->scroll.state = (GdkModifierType) xevent->xbutton.state;
event->button.type = GDK_BUTTON_PRESS;
event->button.window = window;
event->button.time = xevent->xbutton.time;
- event->button.x = xevent->xbutton.x + xoffset;
- event->button.y = xevent->xbutton.y + yoffset;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
event->button.x_root = (gfloat)xevent->xbutton.x_root;
event->button.y_root = (gfloat)xevent->xbutton.y_root;
event->button.axes = NULL;
return_val = FALSE;
break;
}
-
- _gdk_event_button_generate (display, event);
break;
}
xevent->xbutton.button == 6 || xevent->xbutton.button ==7)
{
return_val = FALSE;
- break;
+ goto release_out;
}
event->button.type = GDK_BUTTON_RELEASE;
event->button.window = window;
event->button.time = xevent->xbutton.time;
- event->button.x = xevent->xbutton.x + xoffset;
- event->button.y = xevent->xbutton.y + yoffset;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
event->button.x_root = (gfloat)xevent->xbutton.x_root;
event->button.y_root = (gfloat)xevent->xbutton.y_root;
event->button.axes = NULL;
if (!set_screen_from_root (display, event, xevent->xbutton.root))
{
return_val = FALSE;
- break;
+ goto release_out;
}
-
+
+ release_out:
_gdk_xgrab_check_button_event (window, xevent);
break;
event->motion.type = GDK_MOTION_NOTIFY;
event->motion.window = window;
event->motion.time = xevent->xmotion.time;
- event->motion.x = xevent->xmotion.x + xoffset;
- event->motion.y = xevent->xmotion.y + yoffset;
+ event->motion.x = xevent->xmotion.x;
+ event->motion.y = xevent->xmotion.y;
event->motion.x_root = (gfloat)xevent->xmotion.x_root;
event->motion.y_root = (gfloat)xevent->xmotion.y_root;
event->motion.axes = NULL;
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
- event->crossing.x = xevent->xcrossing.x + xoffset;
- event->crossing.y = xevent->xcrossing.y + yoffset;
+ event->crossing.x = xevent->xcrossing.x;
+ event->crossing.y = xevent->xcrossing.y;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
- event->crossing.x = xevent->xcrossing.x + xoffset;
- event->crossing.y = xevent->xcrossing.y + yoffset;
+ event->crossing.x = xevent->xcrossing.x;
+ event->crossing.y = xevent->xcrossing.y;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
{
GdkRectangle expose_rect;
- expose_rect.x = xevent->xexpose.x + xoffset;
- expose_rect.y = xevent->xexpose.y + yoffset;
+ expose_rect.x = xevent->xexpose.x;
+ expose_rect.y = xevent->xexpose.y;
expose_rect.width = xevent->xexpose.width;
expose_rect.height = xevent->xexpose.height;
break;
}
- expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
- expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
+ expose_rect.x = xevent->xgraphicsexpose.x;
+ expose_rect.y = xevent->xgraphicsexpose.y;
expose_rect.width = xevent->xgraphicsexpose.width;
expose_rect.height = xevent->xgraphicsexpose.height;
: ""));
if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
{
- window_impl->width = xevent->xconfigure.width;
- window_impl->height = xevent->xconfigure.height;
-
+ window_private->width = xevent->xconfigure.width;
+ window_private->height = xevent->xconfigure.height;
+
_gdk_x11_drawable_update_size (window_private->impl);
_gdk_x11_screen_size_changed (screen, xevent);
}
}
window_private->x = event->configure.x;
window_private->y = event->configure.y;
- window_impl->width = xevent->xconfigure.width;
- window_impl->height = xevent->xconfigure.height;
+ window_private->width = xevent->xconfigure.width;
+ window_private->height = xevent->xconfigure.height;
+ _gdk_window_update_size (window);
_gdk_x11_drawable_update_size (window_private->impl);
if (window_private->resize_count >= 1)
if (gdk_event_translate (display, event, &xevent, FALSE))
{
((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+ _gdk_windowing_got_event (display, node, event);
}
else
{
void
_gdk_windowing_gc_set_clip_region (GdkGC *gc,
- const GdkRegion *region)
+ const GdkRegion *region,
+ gboolean reset_origin)
{
GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
x11_gc->have_clip_region = region != NULL;
- gc->clip_x_origin = 0;
- gc->clip_y_origin = 0;
+ if (reset_origin)
+ {
+ gc->clip_x_origin = 0;
+ gc->clip_y_origin = 0;
+ }
x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
}
} u;
};
-struct _GdkWindowParentPos
-{
- gint x;
- gint y;
- gint x11_x;
- gint x11_y;
- GdkRectangle clip_rect;
-};
-
-static void gdk_window_compute_position (GdkWindowImplX11 *window,
- GdkWindowParentPos *parent_pos,
- GdkXPositionInfo *info);
-static void gdk_window_compute_parent_pos (GdkWindowImplX11 *window,
- GdkWindowParentPos *parent_pos);
-static void gdk_window_premove (GdkWindow *window,
- GdkWindowParentPos *parent_pos);
-static void gdk_window_postmove (GdkWindow *window,
- GdkWindowParentPos *parent_pos);
-static void gdk_window_queue_translation (GdkWindow *window,
- GdkRegion *area,
- gint dx,
- gint dy);
-static void gdk_window_clip_changed (GdkWindow *window,
- GdkRectangle *old_clip,
- GdkRectangle *new_clip);
-
-void
-_gdk_x11_window_get_offsets (GdkWindow *window,
- gint *x_offset,
- gint *y_offset)
-{
- GdkWindowImplX11 *impl =
- GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-
- *x_offset = impl->position_info.x_offset;
- *y_offset = impl->position_info.y_offset;
-}
-
-void
-_gdk_window_init_position (GdkWindow *window)
-{
- GdkWindowParentPos parent_pos;
- GdkWindowImplX11 *impl;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- impl =
- GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-
- gdk_window_compute_parent_pos (impl, &parent_pos);
- gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
-}
-
-static void
-gdk_window_copy_area_scroll (GdkWindow *window,
- GdkRectangle *dest_rect,
- gint dx,
- gint dy)
-{
- GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
- GList *l;
-
- if (dest_rect->width > 0 && dest_rect->height > 0)
- {
- GdkGC *gc;
-
- gc = _gdk_drawable_get_scratch_gc (window, TRUE);
-
- gdk_window_queue_translation (window, NULL, dx, dy);
-
- XCopyArea (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- GDK_WINDOW_XID (window),
- gdk_x11_gc_get_xgc (gc),
- dest_rect->x - dx, dest_rect->y - dy,
- dest_rect->width, dest_rect->height,
- dest_rect->x, dest_rect->y);
- }
-
- for (l = obj->children; l; l = l->next)
- {
- GdkWindow *child = (GdkWindow*) l->data;
- GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
- gdk_window_move (child, child_obj->x + dx, child_obj->y + dy);
- }
-}
-
-static void
-compute_intermediate_position (GdkXPositionInfo *position_info,
- GdkXPositionInfo *new_info,
- gint d_xoffset,
- gint d_yoffset,
- GdkRectangle *new_position)
-{
- gint new_x0, new_x1, new_y0, new_y1;
-
- /* Wrap d_xoffset, d_yoffset into [-32768,32767] range. For the
- * purposes of subwindow movement, it doesn't matter if we are
- * off by a factor of 65536, and if we don't do this range
- * reduction, we'll end up with invalid widths.
- */
- d_xoffset = (gint16)d_xoffset;
- d_yoffset = (gint16)d_yoffset;
-
- if (d_xoffset < 0)
- {
- new_x0 = position_info->x + d_xoffset;
- new_x1 = position_info->x + position_info->width;
- }
- else
- {
- new_x0 = position_info->x;
- new_x1 = position_info->x + new_info->width + d_xoffset;
- }
-
- new_position->x = new_x0;
- new_position->width = new_x1 - new_x0;
-
- if (d_yoffset < 0)
- {
- new_y0 = position_info->y + d_yoffset;
- new_y1 = position_info->y + position_info->height;
- }
- else
- {
- new_y0 = position_info->y;
- new_y1 = position_info->y + new_info->height + d_yoffset;
- }
-
- new_position->y = new_y0;
- new_position->height = new_y1 - new_y0;
-}
-
static void
-translate_pos (GdkWindowParentPos *dest, GdkWindowParentPos *src,
- GdkWindowObject *obj, GdkXPositionInfo *pos_info,
- gboolean set_clip)
-{
- dest->x = src->x + obj->x;
- dest->y = src->y + obj->y;
- dest->x11_x = src->x11_x + pos_info->x;
- dest->x11_y = src->x11_y + pos_info->y;
-
- if (set_clip)
- dest->clip_rect = pos_info->clip_rect;
-}
-
-static void
-move (GdkWindow *window, GdkXPositionInfo *pos)
+move (GdkWindow *window, GdkRectangle *pos)
{
XMoveWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), pos->x, pos->y);
}
-static void
-move_relative (GdkWindow *window, GdkRectangle *rect,
- gint dx, gint dy)
-{
- XMoveWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- rect->x + dx, rect->y + dy);
-}
-
static void
move_resize (GdkWindow *window, GdkRectangle *pos)
{
pos->x, pos->y, pos->width, pos->height);
}
-static void
-gdk_window_guffaw_scroll (GdkWindow *window,
- gint dx,
- gint dy)
-{
- GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- gint d_xoffset = -dx;
- gint d_yoffset = -dy;
- GdkRectangle new_position;
- GdkXPositionInfo new_info;
- GdkWindowParentPos parent_pos;
- GList *l;
-
- gdk_window_compute_parent_pos (impl, &parent_pos);
- gdk_window_compute_position (impl, &parent_pos, &new_info);
-
- translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
- _gdk_x11_window_tmp_unset_bg (window, FALSE);;
-
- if (dx > 0 || dy > 0)
- gdk_window_queue_translation (window, NULL, MAX (dx, 0), MAX (dy, 0));
-
- gdk_window_set_static_gravities (window, TRUE);
-
- compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
- &new_position);
-
- move_resize (window, &new_position);
-
- for (l = obj->children; l; l = l->next)
- {
- GdkWindow *child = (GdkWindow*) l->data;
- GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
- child_obj->x -= d_xoffset;
- child_obj->y -= d_yoffset;
-
- gdk_window_premove (child, &parent_pos);
- }
-
- move_relative (window, &new_position, -d_xoffset, -d_yoffset);
-
- if (dx < 0 || dy < 0)
- gdk_window_queue_translation (window, NULL, MIN (dx, 0), MIN (dy, 0));
-
- move_resize (window, (GdkRectangle *) &impl->position_info);
-
- if (impl->position_info.no_bg)
- _gdk_x11_window_tmp_reset_bg (window, FALSE);
-
- impl->position_info = new_info;
-
- g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-}
-
-void
-_gdk_x11_window_scroll (GdkWindow *window,
- gint dx,
- gint dy)
-{
- gboolean can_guffaw_scroll = FALSE;
- GdkRegion *invalidate_region;
- GdkWindowImplX11 *impl;
- GdkWindowObject *obj;
- GdkRectangle src_rect, dest_rect;
-
- obj = GDK_WINDOW_OBJECT (window);
- impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- /* Move the current invalid region */
- if (obj->update_area)
- gdk_region_offset (obj->update_area, dx, dy);
-
- /* impl->position_info.clip_rect isn't meaningful for toplevels */
- if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
- src_rect = impl->position_info.clip_rect;
- else
- {
- src_rect.x = 0;
- src_rect.y = 0;
- src_rect.width = impl->width;
- src_rect.height = impl->height;
- }
-
- invalidate_region = gdk_region_rectangle (&src_rect);
-
- dest_rect = src_rect;
- dest_rect.x += dx;
- dest_rect.y += dy;
- gdk_rectangle_intersect (&dest_rect, &src_rect, &dest_rect);
-
- if (dest_rect.width > 0 && dest_rect.height > 0)
- {
- GdkRegion *tmp_region;
-
- tmp_region = gdk_region_rectangle (&dest_rect);
- gdk_region_subtract (invalidate_region, tmp_region);
- gdk_region_destroy (tmp_region);
- }
-
- gdk_window_invalidate_region (window, invalidate_region, TRUE);
- gdk_region_destroy (invalidate_region);
-
- /* We can guffaw scroll if we are a child window, and the parent
- * does not extend beyond our edges. Otherwise, we use XCopyArea, then
- * move any children later
- */
- if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
- {
- GdkWindowImplX11 *parent_impl = GDK_WINDOW_IMPL_X11 (obj->parent->impl);
- can_guffaw_scroll = ((dx == 0 || (obj->x <= 0 && obj->x + impl->width >= parent_impl->width)) &&
- (dy == 0 || (obj->y <= 0 && obj->y + impl->height >= parent_impl->height)));
- }
-
- if (!obj->children || !can_guffaw_scroll)
- gdk_window_copy_area_scroll (window, &dest_rect, dx, dy);
- else
- gdk_window_guffaw_scroll (window, dx, dy);
-}
-
-void
-_gdk_x11_window_move_region (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy)
-{
- GdkWindowImplX11 *impl;
- GdkWindowObject *private;
- GdkRegion *window_clip;
- GdkRegion *src_region;
- GdkRegion *brought_in;
- GdkRegion *dest_region;
- GdkRegion *moving_invalid_region;
- GdkRectangle dest_extents;
- GdkGC *gc;
-
- private = GDK_WINDOW_OBJECT (window);
- impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
- window_clip = gdk_region_rectangle (&impl->position_info.clip_rect);
-
- /* compute source regions */
- src_region = gdk_region_copy (region);
- brought_in = gdk_region_copy (region);
- gdk_region_intersect (src_region, window_clip);
-
- gdk_region_subtract (brought_in, src_region);
- gdk_region_offset (brought_in, dx, dy);
-
- /* compute destination regions */
- dest_region = gdk_region_copy (src_region);
- gdk_region_offset (dest_region, dx, dy);
- gdk_region_intersect (dest_region, window_clip);
- gdk_region_get_clipbox (dest_region, &dest_extents);
-
- gdk_region_destroy (window_clip);
-
- /* calculating moving part of current invalid area */
- moving_invalid_region = NULL;
- if (private->update_area)
- {
- moving_invalid_region = gdk_region_copy (private->update_area);
- gdk_region_intersect (moving_invalid_region, src_region);
- gdk_region_offset (moving_invalid_region, dx, dy);
- }
-
- /* invalidate all of the src region */
- gdk_window_invalidate_region (window, src_region, FALSE);
-
- /* un-invalidate destination region */
- if (private->update_area)
- gdk_region_subtract (private->update_area, dest_region);
-
- /* invalidate moving parts of existing update area */
- if (moving_invalid_region)
- {
- gdk_window_invalidate_region (window, moving_invalid_region, FALSE);
- gdk_region_destroy (moving_invalid_region);
- }
-
- /* invalidate area brought in from off-screen */
- gdk_window_invalidate_region (window, brought_in, FALSE);
- gdk_region_destroy (brought_in);
-
- /* Actually do the moving */
- gdk_window_queue_translation (window, src_region, dx, dy);
-
- gc = _gdk_drawable_get_scratch_gc (window, TRUE);
- gdk_gc_set_clip_region (gc, dest_region);
-
- XCopyArea (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- GDK_WINDOW_XID (window),
- GDK_GC_XGC (gc),
- dest_extents.x - dx, dest_extents.y - dy,
- dest_extents.width, dest_extents.height,
- dest_extents.x, dest_extents.y);
-
- /* Unset clip region of cached GC */
- gdk_gc_set_clip_region (gc, NULL);
-
- gdk_region_destroy (src_region);
- gdk_region_destroy (dest_region);
-}
-
-static void
-reset_backgrounds (GdkWindow *window)
-{
- GdkWindowObject *obj = (GdkWindowObject *)window;
-
- _gdk_x11_window_tmp_reset_bg (window, FALSE);
-
- if (obj->parent)
- _gdk_x11_window_tmp_reset_bg ((GdkWindow *)obj->parent, FALSE);
-}
-
-static void
-map_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
- GdkWindowObject *obj = (GdkWindowObject *) window;
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- if (!impl->position_info.mapped && pos_info->mapped && GDK_WINDOW_IS_MAPPED (obj))
- XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
-static void
-unmap_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
- GdkWindowObject *obj = (GdkWindowObject *) window;
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- if (impl->position_info.mapped && !pos_info->mapped)
- XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
void
_gdk_window_move_resize_child (GdkWindow *window,
gint x,
{
GdkWindowImplX11 *impl;
GdkWindowObject *obj;
- GdkXPositionInfo new_info;
- GdkWindowParentPos parent_pos;
+ GdkRectangle new_info;
- gint d_xoffset, d_yoffset;
gint dx, dy;
gboolean is_move;
gboolean is_resize;
- GdkRectangle old_pos;
-
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
dy = y - obj->y;
is_move = dx != 0 || dy != 0;
- is_resize = impl->width != width || impl->height != height;
+ is_resize = obj->width != width || obj->height != height;
+#if 0 /* Not right, doesn't take abs_x/y into consideration */
if (!is_move && !is_resize)
return;
+#endif
- old_pos.x = obj->x;
- old_pos.y = obj->y;
- old_pos.width = impl->width;
- old_pos.height = impl->height;
-
obj->x = x;
obj->y = y;
- impl->width = width;
- impl->height = height;
-
- gdk_window_compute_parent_pos (impl, &parent_pos);
- gdk_window_compute_position (impl, &parent_pos, &new_info);
-
- gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
- translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
- d_xoffset = new_info.x_offset - impl->position_info.x_offset;
- d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-
- if (d_xoffset != 0 || d_yoffset != 0)
- {
- GdkRectangle new_position;
-
- gdk_window_set_static_gravities (window, TRUE);
-
- if (d_xoffset < 0 || d_yoffset < 0)
- gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
- compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
- &new_position);
-
- move_resize (window, &new_position);
-
- g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
- move_relative (window, &new_position, dx, dy);
-
- if (d_xoffset > 0 || d_yoffset > 0)
- gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-
- move_resize (window, (GdkRectangle *) &new_info);
-
- reset_backgrounds (window);
-
- map_if_needed (window, &new_info);
-
- impl->position_info = new_info;
-
- g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
- }
- else
- {
- if (is_move && is_resize)
- gdk_window_set_static_gravities (window, FALSE);
-
- unmap_if_needed (window, &new_info);
-
- g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
- if (is_resize)
- move_resize (window, (GdkRectangle *) &new_info);
- else
- move (window, &new_info);
-
- g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-
- reset_backgrounds (window);
-
- map_if_needed (window, &new_info);
-
- impl->position_info = new_info;
- }
-
- if (GDK_WINDOW_IS_MAPPED (obj) && obj->parent && !obj->input_only)
- gdk_window_invalidate_rect ((GdkWindow *)obj->parent, &old_pos, FALSE);
-}
-
-static void
-gdk_window_compute_position (GdkWindowImplX11 *window,
- GdkWindowParentPos *parent_pos,
- GdkXPositionInfo *info)
-{
- GdkWindowObject *wrapper;
- int parent_x_offset;
- int parent_y_offset;
-
- g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
+ obj->width = width;
+ obj->height = height;
- wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-
- info->big = FALSE;
+ new_info.x = obj->x + obj->parent->abs_x;
+ new_info.y = obj->y + obj->parent->abs_y;
+ new_info.width = obj->width;
+ new_info.height = obj->height;
- if (window->width <= 32767)
- {
- info->width = window->width;
- info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
- }
+ if (is_resize)
+ move_resize (window, &new_info);
else
- {
- info->big = TRUE;
- info->width = 32767;
- if (parent_pos->x + wrapper->x < -16384)
- {
- if (parent_pos->x + wrapper->x + window->width < 16384)
- info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->x11_x;
- else
- info->x = -16384 - parent_pos->x11_x;
- }
- else
- info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
- }
-
- if (window->height <= 32767)
- {
- info->height = window->height;
- info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
- }
- else
- {
- info->big = TRUE;
- info->height = 32767;
- if (parent_pos->y + wrapper->y < -16384)
- {
- if (parent_pos->y + wrapper->y + window->height < 16384)
- info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->x11_y;
- else
- info->y = -16384 - parent_pos->x11_y;
- }
- else
- info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
- }
-
- parent_x_offset = parent_pos->x11_x - parent_pos->x;
- parent_y_offset = parent_pos->x11_y - parent_pos->y;
-
- info->x_offset = parent_x_offset + info->x - wrapper->x;
- info->y_offset = parent_y_offset + info->y - wrapper->y;
-
- /* We don't considering the clipping of toplevel windows and their immediate children
- * by their parents, and simply always map those windows.
- */
- if (parent_pos->clip_rect.width == G_MAXINT)
- info->mapped = TRUE;
- /* Check if the window would wrap around into the visible space in either direction */
- else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
- info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
- info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
- info->y + info->height + parent_y_offset > parent_pos->clip_rect.y + 65536)
- info->mapped = FALSE;
- else
- info->mapped = TRUE;
-
- info->no_bg = FALSE;
-
- if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
- {
- info->clip_rect.x = wrapper->x;
- info->clip_rect.y = wrapper->y;
- info->clip_rect.width = window->width;
- info->clip_rect.height = window->height;
-
- gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
-
- info->clip_rect.x -= wrapper->x;
- info->clip_rect.y -= wrapper->y;
- }
- else
- {
- info->clip_rect.x = 0;
- info->clip_rect.y = 0;
- info->clip_rect.width = G_MAXINT;
- info->clip_rect.height = G_MAXINT;
- }
-}
-
-static void
-gdk_window_compute_parent_pos (GdkWindowImplX11 *window,
- GdkWindowParentPos *parent_pos)
-{
- GdkWindowObject *wrapper;
- GdkWindowObject *parent;
- GdkRectangle tmp_clip;
-
- int clip_xoffset = 0;
- int clip_yoffset = 0;
-
- g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
-
- wrapper =
- GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-
- parent_pos->x = 0;
- parent_pos->y = 0;
- parent_pos->x11_x = 0;
- parent_pos->x11_y = 0;
-
- /* We take a simple approach here and simply consider toplevel
- * windows not to clip their children on the right/bottom, since the
- * size of toplevel windows is not directly under our
- * control. Clipping only really matters when scrolling and
- * generally we aren't going to be moving the immediate child of a
- * toplevel beyond the bounds of that toplevel.
- *
- * We could go ahead and recompute the clips of toplevel windows and
- * their descendents when we receive size notification, but it would
- * probably not be an improvement in most cases.
- */
- parent_pos->clip_rect.x = 0;
- parent_pos->clip_rect.y = 0;
- parent_pos->clip_rect.width = G_MAXINT;
- parent_pos->clip_rect.height = G_MAXINT;
-
- parent = (GdkWindowObject *)wrapper->parent;
- while (parent && parent->window_type == GDK_WINDOW_CHILD)
- {
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (parent->impl);
-
- tmp_clip.x = - clip_xoffset;
- tmp_clip.y = - clip_yoffset;
- tmp_clip.width = impl->width;
- tmp_clip.height = impl->height;
-
- gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
-
- translate_pos (parent_pos, parent_pos, parent,
- &impl->position_info, FALSE);
-
- clip_xoffset += parent->x;
- clip_yoffset += parent->y;
-
- parent = (GdkWindowObject *)parent->parent;
- }
-}
-
-static void
-gdk_window_premove (GdkWindow *window,
- GdkWindowParentPos *parent_pos)
-{
- GdkWindowImplX11 *impl;
- GdkWindowObject *obj;
- GdkXPositionInfo new_info;
- gint d_xoffset, d_yoffset;
- GdkWindowParentPos this_pos;
-
- obj = (GdkWindowObject *) window;
- impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- gdk_window_compute_position (impl, parent_pos, &new_info);
-
- gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
- translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
-
- unmap_if_needed (window, &new_info);
-
- d_xoffset = new_info.x_offset - impl->position_info.x_offset;
- d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-
- if (d_xoffset != 0 || d_yoffset != 0)
- {
- GdkRectangle new_position;
-
- if (d_xoffset < 0 || d_yoffset < 0)
- gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
- compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
- &new_position);
-
- move_resize (window, &new_position);
- }
-
- g_list_foreach (obj->children, (GFunc) gdk_window_premove, &this_pos);
-}
-
-static void
-gdk_window_postmove (GdkWindow *window,
- GdkWindowParentPos *parent_pos)
-{
- GdkWindowImplX11 *impl;
- GdkWindowObject *obj;
- GdkXPositionInfo new_info;
- gint d_xoffset, d_yoffset;
- GdkWindowParentPos this_pos;
-
- obj = (GdkWindowObject *) window;
- impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- gdk_window_compute_position (impl, parent_pos, &new_info);
-
- translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
-
- d_xoffset = new_info.x_offset - impl->position_info.x_offset;
- d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-
- if (d_xoffset != 0 || d_yoffset != 0)
- {
- if (d_xoffset > 0 || d_yoffset > 0)
- gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-
- move_resize (window, (GdkRectangle *) &new_info);
- }
-
- map_if_needed (window, &new_info);
-
- reset_backgrounds (window);
-
- impl->position_info = new_info;
-
- g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &this_pos);
+ move (window, &new_info);
}
static Bool
g_queue_push_tail (display_x11->translate_queue, item);
}
-static void
-gdk_window_queue_translation (GdkWindow *window,
- GdkRegion *area,
- gint dx,
- gint dy)
+void
+_gdk_windowing_window_queue_translation (GdkWindow *window,
+ GdkRegion *area,
+ gint dx,
+ gint dy)
{
GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
item->type = GDK_WINDOW_QUEUE_TRANSLATE;
}
gboolean
-_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
- GdkRegion *area)
+_gdk_x11_window_queue_antiexpose (GdkWindow *window,
+ GdkRegion *area)
{
GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
{
GdkWindowImplX11 *impl;
GdkRegion *invalidate_region = gdk_region_rectangle (area);
- GdkRegion *clip_region;
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
}
}
- clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
- gdk_region_intersect (invalidate_region, clip_region);
-
if (!gdk_region_empty (invalidate_region))
- gdk_window_invalidate_region (window, invalidate_region, FALSE);
+ _gdk_window_invalidate_for_expose (window, invalidate_region);
gdk_region_destroy (invalidate_region);
- gdk_region_destroy (clip_region);
-}
-
-static void
-gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
-{
- GdkWindowImplX11 *impl;
- GdkWindowObject *obj;
- GdkRegion *old_clip_region;
- GdkRegion *new_clip_region;
-
- if (((GdkWindowObject *)window)->input_only)
- return;
-
- obj = (GdkWindowObject *) window;
- impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- old_clip_region = gdk_region_rectangle (old_clip);
- new_clip_region = gdk_region_rectangle (new_clip);
-
- /* We need to update this here because gdk_window_invalidate_region makes
- * use if it (through gdk_drawable_get_visible_region
- */
- impl->position_info.clip_rect = *new_clip;
-
- /* Trim invalid region of window to new clip rectangle
- */
- if (obj->update_area)
- gdk_region_intersect (obj->update_area, new_clip_region);
-
- /* Invalidate newly exposed portion of window
- */
- gdk_region_subtract (new_clip_region, old_clip_region);
- if (!gdk_region_empty (new_clip_region))
- {
- _gdk_x11_window_tmp_unset_bg (window, FALSE);;
- gdk_window_invalidate_region (window, new_clip_region, FALSE);
- }
-
- if (obj->parent)
- _gdk_x11_window_tmp_unset_bg ((GdkWindow *)obj->parent, FALSE);
-
- gdk_region_destroy (new_clip_region);
- gdk_region_destroy (old_clip_region);
}
#define __GDK_GEOMETRY_X11_C__
int tmp_n_events = 0;
int i;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+ g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), FALSE);
if (GDK_WINDOW_DESTROYED (window))
/* Nothing */ ;
GdkDisplayX11 *display_x11;
g_return_if_fail (window != NULL);
- g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_WINDOW_IS_X11 (window));
window_private = (GdkWindowObject*) window;
display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
gboolean implicit,
GdkWindow *grab_window)
{
+ g_return_if_fail (window != NULL);
+
if (!GDK_WINDOW_DESTROYED (window))
{
GdkEvent event;
-
event.type = GDK_GRAB_BROKEN;
event.grab_broken.window = window;
event.grab_broken.send_event = 0;
event.grab_broken.keyboard = keyboard;
event.grab_broken.implicit = implicit;
event.grab_broken.grab_window = grab_window;
-
gdk_event_put (&event);
}
}
{
gint return_val;
GdkCursorPrivate *cursor_private;
+ GdkWindow *native;
GdkDisplayX11 *display_x11;
guint xevent_mask;
Window xwindow;
g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-
- display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+
+ native = _gdk_window_get_impl_window (window);
+
+ if (confine_to)
+ confine_to = _gdk_window_get_impl_window (confine_to);
+
+ display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
cursor_private = (GdkCursorPrivate*) cursor;
- xwindow = GDK_WINDOW_XID (window);
- serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
+ xwindow = GDK_WINDOW_XID (native);
+ serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
xconfine_to = None;
xevent_mask |= _gdk_event_mask_table[i];
}
- return_val = _gdk_input_grab_pointer (window,
+ return_val = _gdk_input_grab_pointer (native,
owner_events,
event_mask,
confine_to,
if (return_val == GrabSuccess ||
G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
{
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (native))
{
#ifdef G_ENABLE_DEBUG
if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
return_val = GrabSuccess;
else
#endif
- return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (window),
+ return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (native),
xwindow,
owner_events,
xevent_mask,
if (return_val == GrabSuccess)
{
- if (display_x11->pointer_xgrab_window != NULL &&
- display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
- generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
- FALSE, display_x11->pointer_xgrab_implicit,
- window);
-
- display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
- display_x11->pointer_xgrab_serial = serial;
- display_x11->pointer_xgrab_owner_events = owner_events;
- display_x11->pointer_xgrab_time = time;
- display_x11->pointer_xgrab_implicit = FALSE;
+ _gdk_display_set_has_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
+ window,
+ native,
+ owner_events,
+ event_mask,
+ serial,
+ time,
+ FALSE);
}
return gdk_x11_convert_grab_status (return_val);
}
-/**
- * gdk_pointer_grab_info_libgtk_only:
- * @display: the #GdkDisplay for which to get the grab information
- * @grab_window: location to store current grab window
- * @owner_events: location to store boolean indicating whether
- * the @owner_events flag to gdk_pointer_grab() was %TRUE.
- *
- * Determines information about the current pointer grab.
- * This is not public API and must not be used by applications.
- *
- * Return value: %TRUE if this application currently has the
- * pointer grabbed.
- **/
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
- GdkWindow **grab_window,
- gboolean *owner_events)
-{
- GdkDisplayX11 *display_x11;
-
- g_return_val_if_fail (GDK_IS_DISPLAY (display), False);
-
- display_x11 = GDK_DISPLAY_X11 (display);
-
- if (display_x11->pointer_xgrab_window)
- {
- if (grab_window)
- *grab_window = (GdkWindow *)display_x11->pointer_xgrab_window;
- if (owner_events)
- *owner_events = display_x11->pointer_xgrab_owner_events;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
/*
*--------------------------------------------------------------
* gdk_keyboard_grab
gint return_val;
unsigned long serial;
GdkDisplayX11 *display_x11;
+ GdkWindow *native;
+
+ if (1) return 0; /* TODO: fix */
g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-
- display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
- serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
+ native = _gdk_window_get_impl_window (window);
- if (!GDK_WINDOW_DESTROYED (window))
+ display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
+
+ serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
+
+ if (!GDK_WINDOW_DESTROYED (native))
{
#ifdef G_ENABLE_DEBUG
if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
return_val = GrabSuccess;
else
#endif
- return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
+ return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (native),
+ GDK_WINDOW_XID (native),
owner_events,
GrabModeAsync, GrabModeAsync,
time);
TRUE, FALSE, window);
display_x11->keyboard_xgrab_window = (GdkWindowObject *)window;
+ display_x11->keyboard_xgrab_native_window = (GdkWindowObject *)native;
display_x11->keyboard_xgrab_serial = serial;
display_x11->keyboard_xgrab_owner_events = owner_events;
display_x11->keyboard_xgrab_time = time;
return gdk_x11_convert_grab_status (return_val);
}
+void
+_gdk_windowing_grab_broken (GdkDisplay *display)
+{
+ /* TODO: Move to common code */
+#if 0
+ GdkDisplayX11 *display_x11;
+
+ g_return_if_fail (display != NULL);
+
+ display_x11 = GDK_DISPLAY_X11 (display);
+ generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_grab.window),
+ FALSE,
+ display_x11->pointer_grab.implicit,
+ NULL);
+ display_x11->pointer_grab.window = NULL;
+#endif
+}
+
/**
* gdk_keyboard_grab_info_libgtk_only:
* @display: the display for which to get the grab information
_gdk_xgrab_check_unmap (GdkWindow *window,
gulong serial)
{
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+ GdkDisplay *display = gdk_drawable_get_display (window);
+ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
- if (display_x11->pointer_xgrab_window &&
- serial >= display_x11->pointer_xgrab_serial)
+ if (display->pointer_grab.window &&
+ serial >= display->pointer_grab.serial)
{
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
- GdkWindowObject *tmp = display_x11->pointer_xgrab_window;
+ GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->pointer_grab.native_window);
while (tmp && tmp != private)
tmp = tmp->parent;
if (tmp)
- {
- generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
- FALSE, display_x11->pointer_xgrab_implicit,
- NULL);
- display_x11->pointer_xgrab_window = NULL;
- }
+ _gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
}
if (display_x11->keyboard_xgrab_window &&
void
_gdk_xgrab_check_destroy (GdkWindow *window)
{
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+ GdkDisplay *display = gdk_drawable_get_display (window);
+ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
- if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window)
- {
- generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
- FALSE, display_x11->pointer_xgrab_implicit,
- NULL);
- display_x11->pointer_xgrab_window = NULL;
- }
+ if (window == display->pointer_grab.native_window &&
+ display->pointer_grab.window != NULL)
+ _gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
- if ((GdkWindowObject *)window == display_x11->keyboard_xgrab_window)
+ if ((GdkWindowObject *)window == display_x11->keyboard_xgrab_native_window &&
+ display_x11->keyboard_xgrab_window != NULL)
{
generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
TRUE, FALSE, NULL);
_gdk_xgrab_check_button_event (GdkWindow *window,
XEvent *xevent)
{
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+ GdkDisplay *display = gdk_drawable_get_display (window);
/* track implicit grabs for button presses */
switch (xevent->type)
{
case ButtonPress:
- if (!display_x11->pointer_xgrab_window)
+ if (!display->pointer_grab.window)
{
- display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
- display_x11->pointer_xgrab_serial = xevent->xany.serial;
- display_x11->pointer_xgrab_owner_events = FALSE;
- display_x11->pointer_xgrab_time = xevent->xbutton.time;
- display_x11->pointer_xgrab_implicit = TRUE;
+ _gdk_display_set_has_pointer_grab (display,
+ window,
+ window,
+ FALSE,
+ gdk_window_get_events (window),
+ xevent->xany.serial,
+ xevent->xbutton.time,
+ TRUE);
}
break;
case ButtonRelease:
- if (display_x11->pointer_xgrab_window &&
- display_x11->pointer_xgrab_implicit &&
+ if (display->pointer_grab.window &&
+ display->pointer_grab.implicit &&
(xevent->xbutton.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
{
- display_x11->pointer_xgrab_window = NULL;
+ _gdk_display_unset_has_pointer_grab (display, TRUE, TRUE,
+ xevent->xbutton.time);
}
break;
default:
}
GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
- gint width,
- gint height,
- gint depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+ gint width,
+ gint height,
+ gint depth)
{
GdkPixmap *pixmap;
GdkDrawableImplX11 *draw_impl;
}
GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *drawable,
- const gchar *data,
- gint width,
- gint height)
+_gdk_bitmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height)
{
GdkPixmap *pixmap;
GdkDrawableImplX11 *draw_impl;
}
GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable *drawable,
- const gchar *data,
- gint width,
- gint height,
- gint depth,
- const GdkColor *fg,
- const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ const GdkColor *fg,
+ const GdkColor *bg)
{
GdkPixmap *pixmap;
GdkDrawableImplX11 *draw_impl;
Pixmap _gdk_x11_image_get_shm_pixmap (GdkImage *image);
/* Routines from gdkgeometry-x11.c */
-void _gdk_window_init_position (GdkWindow *window);
void _gdk_window_move_resize_child (GdkWindow *window,
gint x,
gint y,
gulong serial,
GdkRectangle *area);
-void _gdk_x11_window_scroll (GdkWindow *window,
- gint dx,
- gint dy);
-void _gdk_x11_window_move_region (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy);
+gboolean _gdk_x11_window_queue_antiexpose (GdkWindow *window,
+ GdkRegion *area);
+
void _gdk_selection_window_destroyed (GdkWindow *window);
gboolean _gdk_selection_filter_clear_event (XSelectionClearEvent *event);
#define GDK_WINDOW_DISPLAY(win) (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->display)
#define GDK_WINDOW_XROOTWIN(win) (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->xroot_window)
#define GDK_GC_DISPLAY(gc) (GDK_SCREEN_DISPLAY (GDK_GC_X11(gc)->screen))
+#define GDK_WINDOW_IS_X11(win) (GDK_IS_WINDOW_IMPL_X11 (((GdkWindowObject *)win)->impl))
#endif /* __GDK_PRIVATE_X11_H__ */
Atom xtype;
int res;
- g_return_val_if_fail (!window || GDK_IS_WINDOW (window), FALSE);
+ g_return_val_if_fail (!window || GDK_WINDOW_IS_X11 (window), FALSE);
if (!window)
{
GDK_NOTE (MULTIHEAD, g_message ("gdk_property_get(): window is NULL\n"));
}
+ else if (!GDK_WINDOW_IS_X11 (window))
+ return FALSE;
if (GDK_WINDOW_DESTROYED (window))
return FALSE;
Atom xproperty;
Atom xtype;
- g_return_if_fail (!window || GDK_IS_WINDOW (window));
+ g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
if (!window)
{
GDK_NOTE (MULTIHEAD, g_message ("gdk_property_change(): window is NULL\n"));
}
-
+ else if (!GDK_WINDOW_IS_X11 (window))
+ return;
if (GDK_WINDOW_DESTROYED (window))
return;
gdk_property_delete (GdkWindow *window,
GdkAtom property)
{
- g_return_if_fail (!window || GDK_IS_WINDOW (window));
+ g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
if (!window)
{
GDK_NOTE (MULTIHEAD,
g_message ("gdk_property_delete(): window is NULL\n"));
}
+ else if (!GDK_WINDOW_IS_X11 (window))
+ return;
if (GDK_WINDOW_DESTROYED (window))
return;
if (owner)
{
- if (GDK_WINDOW_DESTROYED (owner))
+ if (GDK_WINDOW_DESTROYED (owner) || !GDK_WINDOW_IS_X11 (owner))
return FALSE;
xdisplay = GDK_WINDOW_XDISPLAY (owner);
g_return_if_fail (selection != GDK_NONE);
- if (GDK_WINDOW_DESTROYED (requestor))
+ if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
return;
display = GDK_WINDOW_DISPLAY (requestor);
g_return_val_if_fail (requestor != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
+ g_return_val_if_fail (GDK_WINDOW_IS_X11 (requestor), 0);
display = GDK_WINDOW_DISPLAY (requestor);
- if (GDK_WINDOW_DESTROYED (requestor))
+ if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
goto err;
t = NULL;
static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
static void gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
GdkColormap *cmap);
-static void gdk_window_impl_x11_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height);
-static GdkRegion* gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
static void gdk_window_impl_x11_finalize (GObject *object);
static void gdk_window_impl_iface_init (GdkWindowImplIface *iface);
-#define WINDOW_IS_TOPLEVEL(window) \
- (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
- GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+#define WINDOW_IS_TOPLEVEL(window) \
+ (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
/* Return whether time1 is considered later than time2 as far as xserver
* time is concerned. Accounts for wraparound.
static void
gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
{
- impl->width = 1;
- impl->height = 1;
impl->toplevel_window_type = -1;
}
drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
- drawable_class->get_size = gdk_window_impl_x11_get_size;
-
- /* Visible and clip regions are the same */
- drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
- drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
}
static void
if (!(obj->event_mask & GDK_EXPOSURE_MASK))
return;
- impl->position_info.no_bg = TRUE;
+ impl->no_bg = TRUE;
if (obj->bg_pixmap != GDK_NO_BG)
XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
if (!(obj->event_mask & GDK_EXPOSURE_MASK))
return;
- impl->position_info.no_bg = FALSE;
+ impl->no_bg = FALSE;
if (obj->bg_pixmap == GDK_NO_BG)
return;
if (private->input_only || private->destroyed ||
(private->window_type != GDK_WINDOW_ROOT &&
- !GDK_WINDOW_IS_MAPPED (window)))
+ !GDK_WINDOW_IS_MAPPED (window)) ||
+ !_gdk_window_has_impl (window) ||
+ !GDK_WINDOW_IS_X11 (window))
{
return;
}
if (private->input_only || private->destroyed ||
(private->window_type != GDK_WINDOW_ROOT &&
- !GDK_WINDOW_IS_MAPPED (window)))
+ !GDK_WINDOW_IS_MAPPED (window)) ||
+ !_gdk_window_has_impl (window) ||
+ !GDK_WINDOW_IS_X11 (window))
{
return;
}
}
-static void
-gdk_window_impl_x11_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height)
-{
- g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
-
- if (width)
- *width = GDK_WINDOW_IMPL_X11 (drawable)->width;
- if (height)
- *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
-}
-
-static GdkRegion*
-gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
-{
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (drawable);
- GdkRectangle result_rect;
-
- result_rect.x = 0;
- result_rect.y = 0;
- result_rect.width = impl->width;
- result_rect.height = impl->height;
-
- gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
-
- return gdk_region_rectangle (&result_rect);
-}
-
void
_gdk_windowing_window_init (GdkScreen * screen)
{
private->window_type = GDK_WINDOW_ROOT;
private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
-
- impl->width = WidthOfScreen (screen_x11->xscreen);
- impl->height = HeightOfScreen (screen_x11->xscreen);
-
- _gdk_window_init_position (GDK_WINDOW (private));
+ private->x = 0;
+ private->y = 0;
+ private->abs_x = 0;
+ private->abs_y = 0;
+ private->width = WidthOfScreen (screen_x11->xscreen);
+ private->height = HeightOfScreen (screen_x11->xscreen);
+
_gdk_xid_table_insert (screen_x11->display,
&screen_x11->xroot_window,
screen_x11->root_window);
{
GdkWindowObject *obj = (GdkWindowObject *)window;
GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
- GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
XID xid = GDK_WINDOW_XID (window);
XID xparent = GDK_WINDOW_XID (parent);
* correct value???
*/
size_hints.flags = PSize;
- size_hints.width = impl->width;
- size_hints.height = impl->height;
+ size_hints.width = obj->width;
+ size_hints.height = obj->height;
XSetWMNormalHints (xdisplay, xid, &size_hints);
ensure_sync_counter (window);
}
-GdkWindow *
-_gdk_window_new (GdkWindow *parent,
- GdkWindowAttr *attributes,
- gint attributes_mask)
+void
+_gdk_window_impl_new (GdkWindow *window,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkEventMask event_mask,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
{
- GdkWindow *window;
GdkWindowObject *private;
GdkWindowImplX11 *impl;
GdkDrawableImplX11 *draw_impl;
GdkScreenX11 *screen_x11;
- GdkScreen *screen;
- GdkVisual *visual;
Window xparent;
Visual *xvisual;
Display *xdisplay;
XSetWindowAttributes xattributes;
long xattributes_mask;
XClassHint *class_hint;
- int x, y, depth;
+ int depth;
unsigned int class;
const char *title;
int i;
- g_return_val_if_fail (attributes != NULL, NULL);
+ private = (GdkWindowObject *) window;
- if (!parent)
- {
- GDK_NOTE (MULTIHEAD,
- g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
-
- screen = gdk_screen_get_default ();
- parent = gdk_screen_get_root_window (screen);
- }
- else
- screen = gdk_drawable_get_screen (parent);
-
screen_x11 = GDK_SCREEN_X11 (screen);
-
- g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
-
- if (GDK_WINDOW_DESTROYED (parent))
- return NULL;
+ xparent = GDK_WINDOW_XID (private->parent);
- xparent = GDK_WINDOW_XID (parent);
-
- window = g_object_new (GDK_TYPE_WINDOW, NULL);
-
- private = (GdkWindowObject *) window;
- private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
-
- impl = GDK_WINDOW_IMPL_X11 (private->impl);
- draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+ impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+ private->impl = (GdkDrawable *)impl;
+ draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
draw_impl->wrapper = GDK_DRAWABLE (window);
draw_impl->screen = screen;
xdisplay = screen_x11->xdisplay;
- /* Windows with a foreign parent are treated as if they are children
- * of the root window, except for actual creation.
- */
- if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
- parent = gdk_screen_get_root_window (screen);
-
- private->parent = (GdkWindowObject *)parent;
-
- private->accept_focus = TRUE;
- private->focus_on_map = TRUE;
-
xattributes_mask = 0;
-
- if (attributes_mask & GDK_WA_X)
- x = attributes->x;
- else
- x = 0;
-
- if (attributes_mask & GDK_WA_Y)
- y = attributes->y;
- else
- y = 0;
-
- private->x = x;
- private->y = y;
- impl->width = (attributes->width > 1) ? (attributes->width) : (1);
- impl->height = (attributes->height > 1) ? (attributes->height) : (1);
-
- if (attributes->wclass == GDK_INPUT_ONLY)
- {
- /* Backwards compatiblity - we've always ignored
- * attributes->window_type for input-only windows
- * before
- */
- if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
- private->window_type = GDK_WINDOW_TEMP;
- else
- private->window_type = GDK_WINDOW_CHILD;
- }
- else
- private->window_type = attributes->window_type;
-
- /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
- * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
- */
- if (attributes->wclass == GDK_INPUT_ONLY &&
- GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT &&
- !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
- {
- g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
- attributes->wclass = GDK_INPUT_OUTPUT;
- }
- _gdk_window_init_position (GDK_WINDOW (private));
- if (impl->position_info.big)
- private->guffaw_gravity = TRUE;
-
- if (attributes_mask & GDK_WA_VISUAL)
- visual = attributes->visual;
- else
- visual = gdk_screen_get_system_visual (screen);
xvisual = ((GdkVisualPrivate*) visual)->xvisual;
xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
for (i = 0; i < _gdk_nenvent_masks; i++)
{
- if (attributes->event_mask & (1 << (i + 1)))
+ if (event_mask & (1 << (i + 1)))
xattributes.event_mask |= _gdk_event_mask_table[i];
}
- private->event_mask = attributes->event_mask;
-
if (xattributes.event_mask)
xattributes_mask |= CWEventMask;
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
- if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+ if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
{
- g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
- "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+ /* The common code warns for this case */
xparent = GDK_SCREEN_XROOTWIN (screen);
}
- case GDK_WINDOW_CHILD:
- break;
- default:
- g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
- return NULL;
}
- if (attributes->wclass == GDK_INPUT_OUTPUT)
+ if (!private->input_only)
{
class = InputOutput;
depth = visual->depth;
- private->input_only = FALSE;
- private->depth = depth;
-
- if (attributes_mask & GDK_WA_COLORMAP)
+ if (private->colormap)
{
- draw_impl->colormap = attributes->colormap;
- g_object_ref (attributes->colormap);
+ draw_impl->colormap = private->colormap;
+ g_object_ref (private->colormap);
}
else
{
}
}
- private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
- private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
xattributes.background_pixel = private->bg_color.pixel;
- private->bg_pixmap = NULL;
-
xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
xattributes_mask |= CWBorderPixel | CWBackPixel;
else
{
depth = 0;
- private->depth = 0;
class = InputOnly;
- private->input_only = TRUE;
draw_impl->colormap = gdk_screen_get_system_colormap (screen);
g_object_ref (draw_impl->colormap);
}
xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
- impl->position_info.x, impl->position_info.y,
- impl->position_info.width, impl->position_info.height,
+ private->x + private->parent->abs_x,
+ private->y + private->parent->abs_y,
+ private->width, private->height,
0, depth, class, xvisual,
xattributes_mask, &xattributes);
g_object_ref (window);
_gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
-
+
gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
(attributes->cursor) :
NULL));
- if (private->parent)
- private->parent->children = g_list_prepend (private->parent->children, window);
-
switch (GDK_WINDOW_TYPE (private))
{
case GDK_WINDOW_DIALOG:
XFree (class_hint);
}
- setup_toplevel_window (window, parent);
+ setup_toplevel_window (window, (GdkWindow *)private->parent);
break;
case GDK_WINDOW_CHILD:
- if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+ if (!private->input_only &&
(draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
(draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
{
if (attributes_mask & GDK_WA_TYPE_HINT)
gdk_window_set_type_hint (window, attributes->type_hint);
-
- return window;
}
static GdkEventMask
private->x = attrs.x;
private->y = attrs.y;
- impl->width = attrs.width;
- impl->height = attrs.height;
+ private->width = attrs.width;
+ private->height = attrs.height;
private->window_type = GDK_WINDOW_FOREIGN;
private->destroyed = FALSE;
private->depth = attrs.depth;
- _gdk_window_init_position (GDK_WINDOW (private));
-
g_object_ref (window);
_gdk_xid_table_insert (display, &GDK_WINDOW_XID (window), window);
return window;
{
GdkWindowImplX11 *window_impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
if (!GDK_WINDOW_DESTROYED (window))
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
Window xwindow = GDK_WINDOW_XID (window);
+ gboolean unset_bg;
if (raise)
XRaiseWindow (xdisplay, xwindow);
gdk_x11_window_set_user_time (window, display_x11->user_time);
}
- if (impl->position_info.mapped)
+ unset_bg = !private->input_only &&
+ (private->window_type == GDK_WINDOW_CHILD ||
+ impl->override_redirect) &&
+ gdk_window_is_viewable (window);
+
+ if (unset_bg)
+ _gdk_x11_window_tmp_unset_bg (window, TRUE);
+
+ XMapWindow (xdisplay, xwindow);
+
+ if (unset_bg)
{
- gboolean unset_bg = !private->input_only &&
- (private->window_type == GDK_WINDOW_CHILD ||
- impl->override_redirect) &&
- gdk_window_is_viewable (window);
-
- if (unset_bg)
- _gdk_x11_window_tmp_unset_bg (window, TRUE);
-
- XMapWindow (xdisplay, xwindow);
-
- if (unset_bg)
- {
- _gdk_x11_window_tmp_reset_bg (window, TRUE);
- gdk_window_invalidate_rect (window, NULL, TRUE);
- }
+ _gdk_x11_window_tmp_reset_bg (window, TRUE);
+ gdk_window_invalidate_rect (window, NULL, TRUE);
}
}
}
{
_gdk_window_move_resize_child (window,
x, y,
- impl->width, impl->height);
+ private->width, private->height);
}
else
{
_gdk_window_move_resize_child (window,
private->x, private->y,
width, height);
- _gdk_x11_drawable_update_size (private->impl);
}
else
{
if (impl->override_redirect)
{
- impl->width = width;
- impl->height = height;
+ private->width = width;
+ private->height = height;
_gdk_x11_drawable_update_size (private->impl);
}
else
{
- if (width != impl->width || height != impl->height)
+ if (width != private->width || height != private->height)
private->resize_count += 1;
}
}
private->x = x;
private->y = y;
- impl->width = width;
- impl->height = height;
+ private->width = width;
+ private->height = height;
_gdk_x11_drawable_update_size (private->impl);
}
else
{
- if (width != impl->width || height != impl->height)
+ if (width != private->width || height != private->height)
private->resize_count += 1;
}
}
GdkWindowObject *parent_private;
GdkWindowObject *old_parent_private;
GdkWindowImplX11 *impl;
- gboolean was_toplevel;
-
- if (!new_parent)
- new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
window_private = (GdkWindowObject*) window;
old_parent_private = (GdkWindowObject*)window_private->parent;
XReparentWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
GDK_WINDOW_XID (new_parent),
- x, y);
+ window_private->abs_x + x, window_private->abs_y + y);
- window_private->x = x;
- window_private->y = y;
-
- /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
- * the root window
- */
if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
{
case GDK_WINDOW_ROOT:
case GDK_WINDOW_FOREIGN:
- was_toplevel = WINDOW_IS_TOPLEVEL (window);
-
- if (impl->toplevel_window_type != -1)
- GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
- else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
- GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+ /* Reparenting to toplevel */
+
+ if (!WINDOW_IS_TOPLEVEL (window) &&
+ GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
+ {
+ /* This is also done in common code at a later stage, but we
+ need it in setup_toplevel, so do it here too */
+ if (window_private->toplevel_window_type != -1)
+ GDK_WINDOW_TYPE (window) = window_private->toplevel_window_type;
+ else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+ GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+
+ /* Wasn't a toplevel, set up */
+ setup_toplevel_window (window, new_parent);
+ }
- if (WINDOW_IS_TOPLEVEL (window) && !was_toplevel)
- setup_toplevel_window (window, new_parent);
break;
+
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
- if (WINDOW_IS_TOPLEVEL (window))
+ if (WINDOW_IS_TOPLEVEL (window) &&
+ impl->toplevel)
{
- /* Save the original window type so we can restore it if the
- * window is reparented back to be a toplevel
- */
- impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
- GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
- if (impl->toplevel)
+ if (impl->toplevel->focus_window)
{
- if (impl->toplevel->focus_window)
- {
- XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
- _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
- }
-
- gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
- impl->toplevel);
- g_free (impl->toplevel);
- impl->toplevel = NULL;
+ XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
+ _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
}
+
+ gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
+ impl->toplevel);
+ g_free (impl->toplevel);
+ impl->toplevel = NULL;
}
}
- if (old_parent_private)
- old_parent_private->children = g_list_remove (old_parent_private->children, window);
-
- if ((old_parent_private &&
- (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
- (!old_parent_private && parent_private->guffaw_gravity))
- gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
-
- parent_private->children = g_list_prepend (parent_private->children, window);
- _gdk_window_init_position (GDK_WINDOW (window_private));
-
return FALSE;
}
guint32 timestamp)
{
GdkDisplay *display;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
- if (GDK_WINDOW_DESTROYED (window))
+ g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = GDK_WINDOW_DISPLAY (window);
{
XSizeHints size_hints;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
size_hints.flags = 0;
GdkDisplay *display;
Atom atom;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return GDK_WINDOW_TYPE_HINT_NORMAL;
type = GDK_WINDOW_TYPE_HINT_NORMAL;
{
GdkWindowObject *private;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
private = (GdkWindowObject*) window;
{
GdkToplevelX11 *toplevel;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
{
GdkToplevelX11 *toplevel;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
{
GdkToplevelX11 *toplevel;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
{
XSizeHints size_hints;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
size_hints.flags = 0;
*geom_mask = 0;
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
size_hints = XAllocSizeHints ();
Display *xdisplay;
Window xwindow;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (title != NULL);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
{
GdkDisplay *display;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
display = gdk_drawable_get_display (window);
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ WINDOW_IS_TOPLEVEL (window))
{
if (role)
XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
**/
void
gdk_window_set_startup_id (GdkWindow *window,
- const gchar *startup_id)
+ const gchar *startup_id)
{
GdkDisplay *display;
display = gdk_drawable_get_display (window);
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ WINDOW_IS_TOPLEVEL (window))
{
if (startup_id)
XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
gdk_window_set_transient_for (GdkWindow *window,
GdkWindow *parent)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
+ if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
+ WINDOW_IS_TOPLEVEL (window))
XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
GDK_WINDOW_XID (parent));
gdk_window_x11_set_background (GdkWindow *window,
const GdkColor *color)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkColormap *colormap = gdk_drawable_get_colormap (window);
-
- if (!GDK_WINDOW_DESTROYED (window))
- XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), color->pixel);
-
- private->bg_color = *color;
- gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
-
- if (private->bg_pixmap &&
- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
- private->bg_pixmap != GDK_NO_BG)
- g_object_unref (private->bg_pixmap);
-
- private->bg_pixmap = NULL;
+ XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window), color->pixel);
}
static void
gdk_window_x11_set_back_pixmap (GdkWindow *window,
- GdkPixmap *pixmap,
- gboolean parent_relative)
+ GdkPixmap *pixmap)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
Pixmap xpixmap;
- if (pixmap && !gdk_drawable_get_colormap (pixmap))
- {
- g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
- return;
- }
-
- if (private->bg_pixmap &&
- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
- private->bg_pixmap != GDK_NO_BG)
- g_object_unref (private->bg_pixmap);
-
- if (parent_relative)
- {
- xpixmap = ParentRelative;
- private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
- }
+ if (pixmap == GDK_PARENT_RELATIVE_BG)
+ xpixmap = ParentRelative;
+ else if (pixmap == GDK_NO_BG)
+ xpixmap = None;
else
- {
- if (pixmap)
- {
- g_object_ref (pixmap);
- private->bg_pixmap = pixmap;
- xpixmap = GDK_PIXMAP_XID (pixmap);
- }
- else
- {
- xpixmap = None;
- private->bg_pixmap = GDK_NO_BG;
- }
- }
+ xpixmap = GDK_PIXMAP_XID (pixmap);
if (!GDK_WINDOW_DESTROYED (window))
XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
gulong number_return, bytes_after_return;
guchar *data_return;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ WINDOW_IS_TOPLEVEL (window))
{
atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
"ENLIGHTENMENT_DESKTOP");
{
GdkRectangle rect;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
+ if (!WINDOW_IS_TOPLEVEL (window))
+ return;
+
gdk_window_get_frame_extents (window, &rect);
if (x)
gint wx, wy;
gboolean got_frame_extents = FALSE;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (rect != NULL);
private = (GdkWindowObject*) window;
rect->width = 1;
rect->height = 1;
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
while (private->parent && ((GdkWindowObject*) private->parent)->parent)
int winx = 0;
int winy = 0;
unsigned int xmask = 0;
- gint xoffset, yoffset;
g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
- _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
return_val = NULL;
if (!GDK_WINDOW_DESTROYED (window))
{
}
}
- *x = winx + xoffset;
- *y = winy + yoffset;
+ *x = winx;
+ *y = winy;
*mask = xmask;
return return_val;
if (!GDK_WINDOW_DESTROYED (window))
{
- GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
xevent_mask = StructureNotifyMask | PropertyChangeMask;
+
for (i = 0; i < _gdk_nenvent_masks; i++)
{
if (event_mask & (1 << (i + 1)))
XFree (old_windows);
}
-#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
-
/*
* This needs the X11 shape extension.
* If not available, shaped windows will look
{
GdkWindowObject *private = (GdkWindowObject *)window;
Pixmap pixmap;
- gint xoffset, yoffset;
#ifdef HAVE_SHAPE_EXT
if (GDK_WINDOW_DESTROYED (window))
return;
- _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
- if (xoffset != 0 || yoffset != 0)
- {
- WARN_SHAPE_TOO_BIG ();
- return;
- }
-
if (shape == ShapeBounding
? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
: gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
gint shape)
{
GdkWindowObject *private = (GdkWindowObject *)window;
- gint xoffset, yoffset;
#ifdef HAVE_SHAPE_EXT
if (GDK_WINDOW_DESTROYED (window))
return;
- _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
- if (xoffset != 0 || yoffset != 0)
- {
- WARN_SHAPE_TOO_BIG ();
- return;
- }
-
if (shape_region == NULL)
{
/* Use NULL mask to unset the shape */
{
XSetWindowAttributes attr;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ WINDOW_IS_TOPLEVEL (window))
{
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
{
GdkWindowObject *private;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
private = (GdkWindowObject *)window;
accept_focus = accept_focus != FALSE;
{
private->accept_focus = accept_focus;
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ WINDOW_IS_TOPLEVEL (window))
update_wm_hints (window, FALSE);
}
}
{
GdkWindowObject *private;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
private = (GdkWindowObject *)window;
focus_on_map = focus_on_map != FALSE;
if (private->focus_on_map != focus_on_map)
{
private->focus_on_map = focus_on_map;
-
- if ((!GDK_WINDOW_DESTROYED (window)) && (!private->focus_on_map))
+
+ if ((!GDK_WINDOW_DESTROYED (window)) &&
+ (!private->focus_on_map) &&
+ WINDOW_IS_TOPLEVEL (window))
gdk_x11_window_set_user_time (window, 0);
}
}
glong timestamp_long = (glong)timestamp;
Window xid;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
GdkDisplay *display;
gint n;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
{
GdkToplevelX11 *toplevel;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
{
GdkDisplay *display;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
void
gdk_window_iconify (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_deiconify (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_stick (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_unstick (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_maximize (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_unmaximize (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_fullscreen (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_unfullscreen (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
g_return_if_fail (GDK_IS_WINDOW (window));
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
g_return_if_fail (GDK_IS_WINDOW (window));
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
GdkToplevelX11 *toplevel;
- g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return NULL;
toplevel = _gdk_x11_window_get_toplevel (window);
{
GdkToplevelX11 *toplevel;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
- g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
+ g_return_if_fail (leader == NULL);
- if (GDK_WINDOW_DESTROYED (window) || (leader != NULL && GDK_WINDOW_DESTROYED (leader)))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
GdkWMDecoration decorations)
{
MotifWmHints hints;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
/* initialize to zero to avoid writing uninitialized data to socket */
memset(&hints, 0, sizeof(hints));
MotifWmHints *hints;
gboolean result = FALSE;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return FALSE;
+
hints = gdk_window_get_mwm_hints (window);
if (hints)
MotifWmHints hints;
g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
/* initialize to zero to avoid writing uninitialized data to socket */
memset(&hints, 0, sizeof(hints));
gint root_y,
guint32 timestamp)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
gint root_y,
guint32 timestamp)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowImplX11 *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ if (!WINDOW_IS_TOPLEVEL (window))
+ return;
impl = GDK_WINDOW_IMPL_X11 (private->impl);
{
GdkWindowImplX11 *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ if (!WINDOW_IS_TOPLEVEL (window))
+ return;
impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
if (!impl->use_synchronized_configure)
{
GdkDisplay *display;
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
display = GDK_WINDOW_DISPLAY (window);
#ifdef HAVE_XKB
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
iface->raise = gdk_window_x11_raise;
iface->lower = gdk_window_x11_lower;
iface->move_resize = gdk_window_x11_move_resize;
- iface->scroll = _gdk_x11_window_scroll;
- iface->move_region = _gdk_x11_window_move_region;
iface->set_background = gdk_window_x11_set_background;
iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;
iface->reparent = gdk_window_x11_reparent;
iface->set_child_shapes = gdk_window_x11_set_child_shapes;
iface->merge_child_shapes = gdk_window_x11_merge_child_shapes;
iface->set_static_gravities = gdk_window_x11_set_static_gravities;
- iface->get_offsets = _gdk_x11_window_get_offsets;
+ iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
}
#define __GDK_WINDOW_X11_C__
typedef struct _GdkWindowImplX11Class GdkWindowImplX11Class;
typedef struct _GdkXPositionInfo GdkXPositionInfo;
-struct _GdkXPositionInfo
-{
- gint x;
- gint y;
- gint width;
- gint height;
- gint x_offset; /* Offsets to add to X coordinates within window */
- gint y_offset; /* to get GDK coodinates within window */
- guint big : 1;
- guint mapped : 1;
- guint no_bg : 1; /* Set when the window background is temporarily
- * unset during resizing and scaling */
- GdkRectangle clip_rect; /* visible rectangle of window */
-};
-
-
/* Window implementation for X11
*/
{
GdkDrawableImplX11 parent_instance;
- gint width;
- gint height;
-
- GdkXPositionInfo position_info;
+ guint no_bg : 1; /* Set when the window background is temporarily
+ * unset during resizing and scaling */
GdkToplevelX11 *toplevel; /* Toplevel-specific information */
GdkCursor *cursor;
gint8 toplevel_window_type;